• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    미해결

Controller layer 테스트시 service가 연관되어 있을때 테스트 진행 질문

23.01.14 14:23 작성 조회수 679

1

안녕하세요.

강의 정말 잘 보고 있습니다(모르는 게 이렇게나 많아서 강의보고 찾아보고 공부 정말 많이 되고있습니다)

다름이 아니라 강의를 보고 개인적으로 만들어 보고 있는 상황인데, 테스트를 어떤식으로 짜야되는지 갈피를 잡지 못해서 질문을 드립니다.

단순히 Controller 만 테스트하는건 강의를 통해 학습을 하고 있는데 만약 DB 에 저장되어 있는 데이터가 필요해 조회해야하는 상황에서는 어떻게 단위테스트를 할 수 있을까요?

당장 구글링을 통해 확인한 결과는 Mockito(?) 를 사용하여

'어떤 메소드를 호출하면 개인적으로 정해둔 값을 리턴해!!(given)' 라고 설정해서 테스트를 진행하는데 그러면 실제 DB 에 들어가 있는 데이터값과 다름에도 불구하고 이런 테스트가 올바른지 잘 이해가 되지 않습니다.

//Controller
@PostMapping("/login")
public ResponseEntity<?> loginMember(@RequestBody MemberLoginRequestDTO memberLoginRequestDTO){
    log.info("memberLoginRequestDTO={}", memberLoginRequestDTO.toString());
    return ResponseEntity.status(HttpStatus.OK).body(memberService.login(memberLoginRequestDTO));
}
//Service
@Transactional
public boolean login(MemberLoginRequestDTO memberLoginRequestDTO){
    Member member = memberJpaRepository.findByMemberIdAndPassword(memberLoginRequestDTO.getMemberId(), memberLoginRequestDTO.getPassword())
            .orElseThrow(()->new IllegalArgumentException("회원아이디 혹은 비밀번호를 잘못 입력하셨습니다."));
    return true;
}
//TESTCODE
@Test
@DisplayName("/login 요청시 200 status + true 리턴")
void loginTest() throws Exception {

    //given
    given(memberService.login(any())).willReturn(true);
    //expected
    mockMvc.perform(MockMvcRequestBuilders.post(COMMON_URL + "/login")
                    .contentType(MediaType.APPLICATION_JSON)
                    .content("{\"memberId\" : \"testId\"," +
                            "\"password\" : \"1234\"}")
            )
            .andExpect(MockMvcResultMatchers.status().isOk())
            .andExpect(MockMvcResultMatchers.content().string("true"))
            .andDo(MockMvcResultHandlers.print());
}

간단한 login API 테스트 입니다.

bddmockito 의 given 메소드를 통해 true 를 반환하도록 정의해놓았는데 이런식으로 테스트를 하는게 맞는걸까요?

감사합니다.

답변 1

답변을 작성해보세요.

1

안녕하세요. 호돌맨입니다.
질문을 남겨주셔서 감사합니다.

멋진 시도입니다.
다만 스프링 환경을 모두 실행시켜서 진행하는 통합테스트 코드처럼 보여집니다.

단위테스트로 진행하면 되기 때문에 mockMvc를 사용하지 않으셔도 됩니다.
컨트롤러 객체를 생성하는 형태로.. 순수하게 자바 코드를 테스트하시면 될것같습니다.

아래 예제를 보여드리겠습니다.

    @Test
    @DisplayName("게시글 요청이 정상적으로 진행된다.")
    void test1() {
        // given
        PostResponse response = PostResponse.builder()
                .title("good")
                .build(); // 성공케이스 응답객체 생성

        PostService postService = mock(PostService.class);
        given(postService.get(1L)).willReturn(response); // stubbing

        PostController controller = new PostController(postService);

        // when
        PostResponse result = controller.get(1L);

        // then
        Assertions.assertEquals(result, response);
    }

감사합니다.

leeseongju님의 프로필

leeseongju

질문자

2023.01.18

답변 너무 감사드립니다.
궁금한게 하나 더 있는데 강의를 보다 보니 @WebMvcTest 에서 Repository 인스턴스의 의존성 주입을 위해 @SpringBootTest 와 @AutoConfigureMockMvc 어노테이션으로 변환하셨던데, 통합테스트는와 슬라이스 테스트 각각 언제 사용하는 것이 적합한지 궁금합니다.
단순히 취향에 따라서 개개인별로 다 다르게 테스트를 진행하는 것일까요???

통합 테스트와 단위테스트는 사실 다 하셔야합니다. (정 시간이 없으시면 통합테스트만이라도..)
제 콘텐츠에서는 테스트를 처음 짜 보시는 분들도 계실 수 있을것 같고
하나에 집중하기위해, 직관적으로 이해할 수 있게 통합 테스트만 진행했습니다.
단위테스트를 어떻게 짤지도 일부 모듈에서만 진행할 예정입니다.
감사합니다.