Spring의 Controller Layer를 테스트하기 위해서는
요청을 수행하고 응답을 만들어내는 Servlet API Mock 객체를 사용한다.
오늘 소개할 객체는 MockMvc이다.
MockMvc : Main entry point for server-side Spring MVC test support
MockMvc를 주입받는 방법에는 크게 두가지 방법이 있다.
- @SpringBootTest + @AutoConfigureMockMvc
- @WebMvcTest
각각의 방식에 대해서 알아 보도록 하자.
@SpringBootTest + @AutoConfigureMockMvc
@SpringBootTest는 웹 애플리케이션 컨텍스트와 설정을 모두 불러와 실제 웹 서버에 연결을 시도한다.
만약 Web Layer에 해당하는 부분만 테스트를 진행하고 싶은 경우에는 불필요한 설정도 로드하게 되는 것이다.
통합 테스트를 할때 사용된다.
@SpringBootTest
@AutoConfigureMockMvc
public class SbtControllerTest {
@Autowired
private MockMvc mockMvc;
....
}
@WebMvcTest
해당 설정은 Web Layer에 요청을 처리하기 위해 필요한 Bean들만 로딩한다.
단순히 Spring MVC 컨트롤러를 이용한 요청과 응답을 테스트하고자 한다면 @WebMVCTest를 사용하면 보다 가볍게 테스트할 수 있다.
@WebMvcTest
public class WebMvcControllerTest {
@Autowired
private MockMvc mockMvc;
....
}
경량화되어서 주는 장점도 있지만, 그에 상응하는 단점도 존재한다.
보통의 WebApplication은 Controller - Service - Repository Layer로 구성되어서
Controller와 Service가 Dependency가 존재하는데, @WebMvcTest를 사용하는 경우에는
Controller에 Service 객체를 주입받을 수 없다.
그렇기 때문에 Test를 진행하는 사용자가 Mock 객체를 주입해 주어야 한다.
@WebMvcTest
public class WebMvcControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean //Added !!
private WebMvcService service;
...
}
Service에 해당하는 객체를 Mock으로 주입 받은 경우 테스트 코드 작성 예시는 아래와 같다.
import static org.hamcrest.CoreMatchers.is;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@Test
public void testGet() throws Exception {
ResponseDto dto = new ResponseDto("id2", "sName2", "sCode2", "this is s2");
given(service.findById("id2")).willReturn(dto);
mockMvc.perform(get("/api/{id}", "id2").contentType(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.name", is("sName2")));
}
Controller의 특정 요청을 했을 때, 호출되는 Service의 메서드의 행동을 미리 정의해 놓는 형태이다.
다음으로 getList를 테스트하는 경우에 예시 코드를 보자.
import static org.hamcrest.CoreMatchers.is;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@Test
public void testGetList() throws Exception {
List<StageResponseDto> list = Arrays.asList(
new StageResponseDto("id2", "sName2", "sCode2", "this is s2"));
given(service.findAll()).willReturn(list);
mockMvc.perform(get("/api").contentType(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$").isArray())
.andExpect(jsonPath("$", Matchers.hasSize(1)))
.andExpect(jsonPath("$[0].name", is("sName2")));
}
'Spring > etc' 카테고리의 다른 글
[Spring] @PreAuthorize, @PostAuthorize에서 Custom Security Expression 사용하기 (0) | 2021.11.27 |
---|---|
[Spring] Spring Security Annotation (@PreAuthorize, @PostAuthorize, @Secure) (0) | 2021.11.24 |
[Spring] @WebMvcTest 작성 시 Spring Security 유의사항 (0) | 2021.09.29 |
[Spring] Interceptor란 (+사용 예제) (0) | 2021.09.05 |
[Spring] 구동 시점 로직 추가 (CommandLineRunner ApplicationRunner) (0) | 2021.09.02 |