SMALL

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")));
	}

 

 

 

 

LIST

+ Recent posts