@WebMvcTest
- MVC를 위한 테스트, 컨트롤러가 예상대로 동작하는지 테스트하는데 사용된다.
- 웹상에서 요청과 응답에 대해 테스트할 수 있음.
- 시큐리티, 필터까지 자동으로 테스트하며, 수동으로 추가/삭제 가능.
- @SpringBootTest 어노테이션보다 가볍게 테스트할 수 있음.
- @WebMvcTest 어노테이션을 사용시 다음 내용만 스캔 하도록 제한한다.
- @Controller
- @ControllerAdvice
- @JsonComponent
- Converter
- GenericConverter
- Filter
- HandlerInterceptor
- WebMvcConfigurer
- HandlerMethodArgumentResolver
- MockBean, MockMVC를 자동 구성하여 테스트 가능하도록 한다.
- Spring Security의 테스트도 지원 한다. -> 로그인, 로그아웃, 세션, 필터까지 테스트할 수 있다.
- @WebMvcTest를 사용하기 위해 테스트할 특정 컨트롤러 클래스를 명시 하도록 한다.
- 예시는 아래와 같다.
@WebMvcTest(TestRestController.class)
@Slf4j
class TestRestControllerTest {
@Autowired MockMvc mvc;
@MockBean
private TestService testService;
protected MediaType contentType =
new MediaType(MediaType.APPLICATION_JSON.getType(),
MediaType.APPLICATION_JSON.getSubtype(),
StandardCharsets.UTF_8);
@Test void getListTest() throws Exception {
//given
TestVo testVo = TestVo.builder()
.id("hyunwook")
.name("현욱")
.build();
//given
given(testService.selectOneMember("hyunwook"))
.willReturn(testVo);
//when
final ResultActions actions = mvc.perform(get("/testValue2")
.contentType(contentType))
.andDo(print());
//then
actions
.andExpect(status()
.isOk())
.andExpect(content().contentType(contentType))
.andExpect(jsonPath("$.name", is("현욱")))
.andDo(print());
}
}
- given에서 해당 객체를 생성 처리한다.
- when에서 목객체를 기반으로 미리 정의된 객체를 반환 처리한다.
- 선언해둔 contentType 을 지정해 준다.
- then에서 해당 객체의 응답값을 검사 처리한다.
코드 예시
@WebMvcTest(DMakerController.class)
@MockBean(JpaMetamodelMappingContext.class)
class DMakerControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private DMakerService dMakerService;
protected MediaType contentType =
new MediaType(MediaType.APPLICATION_JSON.getType(),
MediaType.APPLICATION_JSON.getSubtype(),
StandardCharsets.UTF_8);
@Test
void getAllDevelopers() throws Exception {
//given
DeveloperDto seniorBEDeveloper = DeveloperDto.builder()
.developerSkillType(DeveloperSkillType.BACK_END)
.developerLevel(DeveloperLevel.SENIOR)
.memberId("memberId")
.build();
DeveloperDto juniorFEDeveloper = DeveloperDto.builder()
.developerSkillType(DeveloperSkillType.FRONT_END)
.developerLevel(DeveloperLevel.JUNIOR)
.memberId("memberId2")
.build();
given(dMakerService.getAllEmployedDevelopers())
.willReturn(Arrays.asList(seniorBEDeveloper, juniorFEDeveloper));
//when
//then
mockMvc.perform(get("/developers").contentType(contentType))
.andExpect(status().isOk())
.andExpect(
jsonPath("$.[0].developerSkillType",
is(DeveloperSkillType.BACK_END.name())))
.andExpect(
jsonPath("$.[0].developerLevel",
is(DeveloperLevel.SENIOR.name())))
.andExpect(
jsonPath("$.[1].developerSkillType",
is(DeveloperSkillType.FRONT_END.name())))
.andExpect(
jsonPath("$.[1].developerLevel",
is(DeveloperLevel.JUNIOR.name())));
}
@Test
void testErrorMessage() throws Exception {
//given
given(dMakerService.getAllEmployedDevelopers())
.willThrow(new DMakerException(DMakerErrorCode.NO_DEVELOPER));
//when
//then
mockMvc.perform(get("/developers").contentType(contentType))
.andDo(print())
.andExpect(status().isOk())
.andExpect(
jsonPath("$.errorCode",
is(DMakerErrorCode.NO_DEVELOPER.name())));
}
}
@WebMvcTest 장점
- WebApplication 관련된 Bean들만 등록하기 때문에 통합 테스트보다 빠르다.
- 통합 테스트를 진행하기 어려운 테스트를 진행 가능하다.
- ex) 결제 모듈 API를 콜하며 안되는 상황에서 Mock을 통해 가짜 객체를 만들어 테스트 가능.
@WebMvcTest 단점
- 요청부터 응답까지 모든 테스트를 Mock 기반으로 테스트하기 때문에 실제 환경에서는 제대로 동작하지 않을 수 있다.
@WebFluxTest
- Spring WebFluex component에 초점을 맞춰 Spring WebFlux test에 사용되는 annotation 이다.
- 전체 auto-configuration을 실행하지 않는 대신 WebFlux와 연관된 configuration만 실행한다.
- @Controller, @ControllerAdvice, @JsonComponent, Converter/GenericConverter, WebFluxConfigurer bean을 생성하고 적재한다.
- 하지만 @Component, @Service, @Repository bean은 생성되지 않는다.
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class SampleControllerTest {
@Autowired
WebTestClient webTestClient;
@MockBean
SampleService mockSampleService;
@Test
public void helloTest() throws Exception {
when(mockSampleService.getName()).thenReturn("dave");
webTestClient.get().uri("/hello").exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("hello dave");
}
}
- SpringMvcWebFlux에 추가된 RestClient 중 하나로 asynchronous하게 동작하여 r
equest에 대한 response가 도착할 때 callback
을 실행할 수 있습니다.
비동기 연결방식으로 동작
하기 때문에 테스트 코드로 WebClient와 동일한 API를 사용할 수 있다.
- WebTestClient를 사용하려면 project에 spring-boot-starter-webflux 의존성을 추가해야 한다.
REFERENCES