Home Controller 단위 테스트
Post
Cancel

Controller 단위 테스트

스프링 웹 애플리케이션에서 Controller 계층 단위 테스트

Controller 계층의 역할

layered architecture에서 controller 계층은 presentation 계층으로도 불린다.
수신한 client의 요청을 하위 계층인 service 계층에게 위임하는 역할을 한다.

controller 계층에서의 단위 테스트는 수신한 client의 요청이 올바른지 검증하고 API 응답에 대한 검증을 한다.

Base Class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@WebMvcTest(controllers = {
    PostController.class,
    ...
})
public class ControllerTest {
    @Autowired
    protected MockMvc mockMvc;

    @Autowired
    protected ObjectMapper objectMapper;

    @MockBean
    protected PostService PostService;
    ...
}
  • @WebMvcTest
    • Spring Application Context 전체가 아닌 Presentation 계층에 대한 컴포넌트(Bean)만 로드한다.
    • presentation 계층이 아닌 하위 계층의 객체는 @MockBean으로 등록해서 주입받는다.
    • controllers에 테스트 대상 controller 클래스를 넣어준다.
  • @MockBean
    • @WebMvcTest를 위한 Spring container에 Mockito의 Mock 객체를 추가해준다.
    • 위 코드에서 @WebMvcTest로 PostService가 로드가 되지 않은 상황이고 이를 Mock 객체화해서 Spring Context에 추가하기 위함
  • MockMvc
    • 웹 어플리케이션을 서버에 배포하지 않고 테스트용 MVC환경을 만들어 요청 및 전송, 응답기능을 제공해주는 유틸리티
  • ObjectMapper
    • Java Object <-> Json Data 간 변환을 위한 유틸리티

Controller

1
2
3
4
5
6
7
8
9
10
11
12
@RestController
@RequiredArgsConstructor
public class PostController {

    private final PostSerivce postService;

    @PostMapping("/api/v1/posts")
    public PostResposne createPost(@Valid @RequestBody PostCreateRequest request){
        return postService.createPost(request);
    }

}

endpoint가 /api/v1/posts이고, method가 Post인 createPost에 대한 테스트 코드를 작성해보자.

Test Class Code

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
@WebMvcTest(controllers = PostController.class)
class PostControllerTest extends ControllerTest {

    @DisplayName("게시글 생성 요청시, 게시글을 저장한다.")
    @Test
    void createPost(){
        // given
        PostCreateRequest request = PostCreateRequest.builder()
                .title("테스크 코드 작성법")
                .content("본문 내용")
                .author("sehyeong")
                .build();

        PostCreateResponse expected = PostCreateResponse.builder()
                .id(1L).build();

        given(postService.createPost(request)).willReturn(expected);

        // when
        ResultActions resultActions = mockMvc.perform(
                        post("/api/v1/posts")
                                .contentType(MediaType.APPLICATION_JSON)
                                .content(objectMapper.writeValueAsString(request)))
                .andDo(print());

        // then
        resultActions
                .andExpect(status().isCreated())
                .andExpect(header().string("Location", "/api/v1/posts/1"));

}

mockMvc를 통해서 원하는 endpoint에 요청을 보내고 응답에 대한 상태코드 확인 정도로 작성한다. 앞서 다룬 repository와 service 계층 테스트와 달리 이번 테스트는 하위 계층을 mocking 하고 controller layer만 테스트하는 유닛 테스트의 성격에 가깝다. 글의 서두에서도 언급했듯이 Client의 요청과 API 스펙에 맞는 응답코드 정도를 확인한다.

Refercence

This post is licensed under CC BY 4.0 by the author.

Serivce 테스트

Controller 통합 테스트