on
[Spring Boot] Controller Test
[Spring Boot] Controller Test
Servicee 나 Repository에 대해 테스트 코드를 짜는 것은 조금은 익숙하나, Controller 레이어를 구성하고 테스트 하기 위해서는 Postman이나 Web UI 테스트를 진행해왔다. 이번에는 어플리케이션 수준에서 Controller 테스트를 하는 방법을 간단하게 알아보고자 한다.
Environment
- Junit 5
- Spring Boot 2.1.7
- JPA (Hibernate)
Controller Test
* Service, Repository, DTO 및 Entity에 대한 코드는 따로 명시하진 않는다.
Controller에 대해 테스트를 하려면 Mock이라는 개념이 필요한데, 이에 대해서는 다음에 자세히 알아보도록 하고, 이번에는 어떻게 사용하는지만 알아보자.
package org.gorany.bootbook.api.controller; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.test.web.servlet.MockMvc; /** * @WebMvcTest * - JPA 기능은 동작하지 않는다. * - 여러 스프링 테스트 어노테이션 중, Web(Spring MVC)에만 집중할 수 있는 어노테이션 * - @Controller, @ControllerAdvice 사용 가능 * - 단, @Service, @Repository등은 사용할 수 없다. * */ @WebMvcTest(HelloController.class) class HelloControllerTest { @Autowired /** * 웹 API 테스트할 때 사용 * 스프링 MVC 테스트의 시작점 * HTTP GET,POST 등에 대해 API 테스트 가능 * */ MockMvc mvc; @Test @DisplayName("Hello Test") void Hello_Test() throws Exception { //given String hello = "hello"; //when //then mvc.perform(get("/hello")) //MockMvc를 통해 /hello 주소로 GET 요청 //mvc.perform()의 결과를 검증 .andExpect(status().isOk()) //200 상태 .andExpect(content().string(hello)); //응답 본문의 내용을 검증 } @Test @DisplayName("헬로 디티오 컨트롤러 테스트") void HelloControllerDtoTest() throws Exception { //given String name = "Test"; int amount = 10000; //when //then mvc.perform(get("/hello/dto") .param("name", name) .param("amount", Integer.toString(amount)) ) .andExpect(status().isOk()) .andExpect(jsonPath("$.name").value(name)) .andExpect(jsonPath("$.amount").value(amount)); } }
위와 같이 오직 Controller에 대해서만 테스트 검증을 할 때는 @WebMvcTest 를 사용하면 된다. 하지만 @Service, @Repository 등도 같이 사용해야하는 로직이라면 어떻게 해야할까? 그리고 JPA도 사용해야한다면?
@SpringBootTest 어노테이션을 사용해야 한다. 하지만 이 어노테이션만 가지고는 MockMvc를 사용할 수 없다. 따라서 어노테이션이 하나 더 필요하다. -> @AutoConfigureMockMvc
package org.gorany.bootbook.api.controller; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import com.fasterxml.jackson.databind.ObjectMapper; import org.gorany.bootbook.api.dto.PostsSaveRequestDto; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; @SpringBootTest @AutoConfigureMockMvc class PostsControllerTest { @Autowired ObjectMapper mapper; @Autowired MockMvc mvc; private static final String BASE_URL = "/api/v1"; @Test @DisplayName("저장 테스트") void save_test() throws Exception { //given String title = "Test title"; String content = "Test content"; String author = "gorany"; //when /** * Object를 JSON으로 변환 * */ String body = mapper.writeValueAsString( PostsSaveRequestDto.builder().author(author).content(content).title(title).build() ); //then mvc.perform(post(BASE_URL + "/posts") .content(body) //HTTP Body에 데이터를 담는다 .contentType(MediaType.APPLICATION_JSON) //보내는 데이터의 타입을 명시 ) .andExpect(status().isOk()) .andExpect(content().string("1")); } }
#References
스프링 부트와 AWS로 혼자 구현하는 웹 서비스, 이동욱, 프리렉
from http://dev-gorany.tistory.com/354 by ccl(A) rewrite - 2021-12-04 18:01:31