Controller
SpringBoot에서 JUnit5를 사용하여 테스트 코드를 작성할 때, @SpringBootTest 어노테이션을 자주 쓰는데, 상황에 따라 @WebMvcTest를 쓰는게 좋을 떄도 있다. @SpringBootTest는 프로젝트의 전체 컨텍스트를 로드하여 빈을 주입하기 때문에 속도가 느리고, 통합 테스트를 할 때 많이 사용한다. 필요한 빈만 등록하여 테스트를 진행하고자 한다면, 슬라이스 테스트 어노테이션인 @WebMvcTest를 사용하는 것이 효율적이다.
슬라이스 테스트란?
특정 부분만 테스트할 수 있는 테스트를 말한다. 아래는 대표적인 슬라이스 테스트 어노테이션이다. @WebMvcTest - Controller를 테스트할 수 있도록 관련 설정을 제공 - 특정 컴포넌트만 Bean으로 등록한다. - 이 밖에 테스트를 하는 데 필요하지 않은 @Service, @Repository 등은 Bean으로 등록하지 않는다. 이 밖에도 WebFluxTest, DataJpaTest, DataJpaTest, JsonTest, RestClientTest 등이 존재한다.
@WebMvcTest는 MVC 부분 슬라이스 테스트로, 보통 컨트롤러 하나만 테스트하고 싶을 때 사용한다. 가끔 NoSuchDefinitionException 오류가 나는데, Service와 같은 일반적인 컴포넌트는 생성되지 않는 특성 때문이다. 해당 컨트롤러를 생성하는 데 필요한 다른 빈을 정의하지 못해 발생한다. 따라서 이런 경우에는 @MockBean 을 사용해서 필요한 의존성을 채워주어야 한다.
MockMvc
MockMvc를 활용한 Controller 슬라이스 테스트를 진행해본다.
GET
@Autowired
private MockMvc mockMvc;
@Autowired
private UserRepository userRepository;
@Autowired
private ObjectMapper objectMapper;
@DisplayName("회원정보 조회")
@Test
public void findUserByEmailTest() throws Exception {
User user = User.builder()
.name("name")
.email("blabla@gmail.com")
.password("pwd")
.role("ROLE_USER")
.build();
Long id = userRepository.save(user);
mockMvc.perform(get("/api/user/") + id)
.andExpect(status().isOk())
.andDo(print());
}
POST
@Autowired
private MockMvc mockMvc;
@Autowired
private ObjectMapper objectMapper;
@DisplayName("회원가입")
@Test
public void signupTest() throws Exception {
Map<String, String> input = new HashMap<>();
input.put("name", "kimdozzi");
input.put("email", "dozzi@gmail.com");
input.put("password", "pwd");
mockMvc.perform(post("/signup")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(input))) //Map으로 만든 input을 json형식의 String으로 만들기 위해 objectMapper를 사용
.andExpect(status().isOk())
.andDo(print());
}
PATCH
@Autowired
private MockMvc mockMvc;
@Autowired
private UserRepository userRepository;
@Autowired
private ObjectMapper objectMapper;
@DisplayName("회원정보 수정")
@Test
public void UpdateUser() throws Exception {
User user = User.builder()
.name("kimdozzi")
.email("dozzi@gmail.com")
.password("pwd")
.role("ROLE_USER")
.build();
Long id = userRepository.save(user);
Map<String, String> updateUser = new HashMap<>();
updateUser.put("name", "updated_dozzi");
updateUser.put("password", "updated_pwd");
mockMvc.perform(patch("/user/" + id)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(input)))
.andExpect(status().isOk())
.andDo(print());
}
DELETE
@Autowired
private MockMvc mockMvc;
@Autowired
private UserRepository userRepository;
@DisplayName("회원정보 삭제")
@Test
public void deleteUserTest() throws Exception {
User user = User.builder()
.name("kimdozzi")
.email("dozzi@gmail.com")
.password("pwd")
.role("ROLE_USER")
.build();
Long id = userRepository.save(user);
mockMvc.perform(delete("/user/" + id))
.andExpect(status().isOk())
.andDo(print());
Assertions.assertThat(userRepository.findByName("kimdozzi")).isEmpty());
}
참고 자료
스프링 MockMvc를 이용한 get, post, patch, delete 테스트
MockMvc란? MockMvc는 어플리케이션을 서버에 배포하지 않고도 스프링 MVC의 테스트를 진행할 수 있게 도와주는 클래스이다.
ip99202.github.io
MockMvc :: Spring Framework
The Spring MVC Test framework, also known as MockMvc, provides support for testing Spring MVC applications. It performs full Spring MVC request handling but via mock request and response objects instead of a running server. MockMvc can be used on its own t
docs.spring.io
Mockito를 활용하여 테스트 코드 작성하기
Mockito 란? Mockito란 Java 오픈소스 테스트 프레임워크입니다. Mockito를 사용하면 실제 객체를 모방한 가짜 객체, Mock 객체 생성이 가능해집니다. 개발자는 이 Mock 객체를 통해 테스트를 보다 간단하
www.nextree.io