비즈니스로직이 녹아들어간 Service.class에서 간혹
interface를 맴버변수로 DI시키는 경우가 있었습니다.
프로젝트 진행중 일부 소스를 발췌했습니다.
아래 소스중 TalkMessage.class가 interface이고
TalkMessage를 구현하는 구현체가 2개정도 있었습니다.
그래서 멤버필드를 list로 주입받았습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
@Service
public class TalkMessageApiClientService {
private final TalkMessageApiClient talkMessageApiClient;
private final List<TalkMessage> talkMessages; //요놈이 interface
public TalkMessageApiClientService(TalkMessageApiClient talkMessageApiClient,
List<TalkMessage> talkMessages) {
this.talkMessageApiClient = talkMessageApiClient;
this.talkMessages = talkMessages;
}
public List<TalkMessageSenderView> getTalkMessageSendList(TalkMessageRequest req){
List<FeignTalkMessageResponse> res = getTalkMessageApi(req);
List<Integer> userIds = res.stream().map(FeignTalkMessageResponse::getReceiverId).distinct().collect(Collectors.toList());
return getTalkMessageClass(req).sendConvert(userIds, res, req);
}
public List<TalkMessageReceiveView> getTalkMessageReceiveList(TalkMessageRequest req){
List<FeignTalkMessageResponse> res = getTalkMessageApi(req);
List<Integer> userIds = res.stream().map(FeignTalkMessageResponse::getSenderId).distinct().collect(Collectors.toList());
return getTalkMessageClass(req).receiveConvert(userIds, res, req);
}
private List<FeignTalkMessageResponse> getTalkMessageApi(TalkMessageRequest req) {
ApiResponse<List<FeignTalkMessageResponse>> res = Optional.of(talkMessageApiClient.findMessages(
FeignTalkMessageRequest.builder()
.deleteYn(req.getDeleteYn())
.isSearching(!req.getKeyword().isEmpty())
.partnerIds(req.getKeyword().isEmpty() ? Collections.emptyList() : getTalkMessageClass(req).getPartnerIds(req) )
.readYn(req.getConfirmYn())
.senderOrReceiver(req.getTabName().toUpperCase())
.talkType(req.getTalkType())
.teacherId(req.getAdmId())
.build(), req.getOffset(), req.getLimit()))
.filter(data -> !data.isBadRequest())
.orElseThrow(() -> new ValidationException("API호출 실패했습니다."));
return res.getData();
}
private TalkMessage getTalkMessageClass(TalkMessageRequest req){
return talkMessages.stream()
.filter(data -> req.getTalkType().equals(data.getTalkType()))
.findFirst()
.orElseThrow(() -> new NoDataException("정상적인 호출이 아닙니다."));
}
}
|
cs |
위의 비즈니스 로직에 대해서 Test를 작성하려고 했었습니다.
기존처럼 Mock객체를 주입해서 했었는데
당연하게도 오류가 나면서 테스트가 정상적으로 이뤄지지 않았고
해당interface에 실제 구현되어있는 class를 mock으로 주입해주면서
해당오류는 해결되었으며 테스트도 정상적으로 진행했습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
@RunWith(MockitoJUnitRunner.class)
public class TalkMessageApiClientServiceTest{
@Mock
private TalkMessageApiClient talkMessageApiClient;
@Spy
private List<TalkMessage> talkMessages = new ArrayList<>();
@InjectMocks
private TalkMessageApiClientService talkMessageApiClientService;
@Mock
private ParentTalk parentTalk;
@Mock
private StudentTalk studentTalk;
@Before
public void setup(){
given(parentTalk.getTalkType()).willReturn("P");
given(studentTalk.getTalkType()).willReturn("S");
given(parentTalk.sendConvert(anyList(), anyList(), any())).willReturn(
Arrays.asList(
TalkMessageSenderView.builder().talkType("학부모").talkNo(123L).groupId(234).readYn("N").msgContent("내용1").build(),
TalkMessageSenderView.builder().talkType("학부모").talkNo(456L).groupId(567).readYn("N").msgContent("내용2").build()));
given(studentTalk.receiveConvert(anyList(), anyList(), any())).willReturn(
Arrays.asList(
TalkMessageReceiveView.builder().talkType("학생").talkNo(123L).groupId(234).readYn("Y").msgContent("학생받기1").stuId(1111).build(),
TalkMessageReceiveView.builder().talkType("학생").talkNo(456L).groupId(567).readYn("Y").msgContent("학생받기2").stuId(2222).build(),
TalkMessageReceiveView.builder().talkType("학생").talkNo(789L).groupId(890).readYn("Y").msgContent("학생받기3").stuId(3333).build()
)
);
talkMessages.add(parentTalk);
talkMessages.add(studentTalk);
}
@Test
public void getTalkMessageSendList(){
given(talkMessageApiClient.findMessages(any(), anyInt(), anyInt())).willReturn(this.getTalkMessage());
List<TalkMessageSenderView> talkMessageSenderViews = talkMessageApiClientService.getTalkMessageSendList(TalkMessageRequest.builder().admId(1).talkType("P").keyword("").searchType("").tabName("SENDER").limit(1000).offset(0).build());
assertThat(talkMessageSenderViews, is(notNullValue()));
assertThat(talkMessageSenderViews.size(), is(2));
assertThat(talkMessageSenderViews.get(0).getTalkNo(), is(123L));
}
}
|
cs |
제가 내린 결론?이라고 해야되나...
평소에 @Mock 어노테이션과 @InjectMocks만으로 테스트를 진행했었는데
@Spy 어노테이션은 interface를 주입해주는
즉 임시객체를 만드는것은 똑같으나 결국은
다시 주입해줘야 하는 객체를 만들때 사용하면? 되는 어노테이션 같습니다.
감사합니다.
'IT > 개발' 카테고리의 다른 글
spring cloud (0) | 2021.10.12 |
---|---|
Kafka (0) | 2021.10.12 |
JAVA 8 groupingBy, mapping, collectingAndThen (0) | 2021.01.19 |
spring junit void test (0) | 2020.12.01 |
spring file delete (0) | 2020.10.29 |