Springboot Controller 테스트 해보기 1탄 (Mock, MockMvc)
참고
https://gocheat.github.io/spring/spring_test-1/
https://ktko.tistory.com/entry/%EC%8A%A4%ED%94%84%EB%A7%81Spring-MockMvc-%ED%85%8C%EC%8A%A4%ED%8A%B8
https://we1cometomeanings.tistory.com/65
실무에서 단위테스트로 간단한 진행만 하지 TDD로 개발은 하지 않고 있는데 개발하면 할 수록 중요성이 너무 느껴서 열심히 사용해 보려고 한다.
Mock
- 네트워크, 데이터베이스 등에 의존하고 있는 메서드를 테스트하기 위해 가짜 객체를 만들어서 진행하는 테스트
- 테스트 작성을 위한 환경 구축이 어렵고 메소드 내에 타 외부 서비스 혹은 미들웨어에 의존적인 경우 사용
Mockito 프레임워크
- Mock 객체를 만드는 번거로움을 줄여주기 위한 프레임워크
@ExtendWith(MockitoExtension.class)
: Mockito의 Mock 객체를 사용
@Mock
: Mock 객체
@InjectMocks
: @Mock 객체를 주입할 주체 객체
public class AuthController {
@PostMapping("/save")
public ApiResponse save(@RequestBody User user) {
if (userService.getUser(user.getUserName()) != null) {
return ApiResponse.fail();
}
userService.save(user);
return ApiResponse.success(HttpStatus.OK.name(), null);
}
}
위의 코드를 테스트 하려고 할 때면
@Mock
어노테이션으로 UserService
를 Mock 객체로 만들어주고
@InjectMocks
어노테이션으로 AuthController
를 객체를 주입 할 주제 객체로 선언해주면 될 줄 알았으나 생각해보니 userService를 Test 코드 자체에서 사용하는 것이 아니라 Controller 안에서 사용하니까 다른 방법이 필요해 보였다.
MockMvc
그 다른 방법으로 사용하는 것이 MockMvc 방법이다.
웹 애플리케이션을 애플리케이션 서버에 배포하지 않고 스프링의 MVC 동작을 테스트 할 수 있는 클래스이다.
사실 처음에는 비즈니스 로직을 구현하는 서비스단을 테스트하면 컨트롤러 단을 테스트 할 필요가 있을까? 싶었지만 일반적인 단위 테스트 형태가 아니라 통합 테스트 관점으로 생각하면 의미가 있다고 한다.
웹 환경에서 컨트롤러를 테스트하기 위해서는 서블릿 컨테이너 구동, DispatcherServlet 객체가 메모리에 올라갸아함. 서블릿 컨테이너를 모킹하면 실제가 아니라 테스트용 모형 컨테이너를 사용하면 간단하게 컨트롤러를 테스트 할 수 있음. --> 이 부분을 위해서 @WebMvcTest
또는 @AutoConfigureMockMvc
를 사용한다.
완성된 테스트 코드
package com.studygram;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.studygram.common.oauth.ProviderType;
import com.studygram.common.oauth.RoleType;
import com.studygram.controller.AuthController;
import com.studygram.domain.User;
import com.studygram.service.UserService;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
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.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
@AutoConfigureMockMvc
public class AuthControllerTest {
@Mock
private User user;
@Autowired
private MockMvc mockMvc;
AutoCloseable openMocks;
ObjectMapper objectMapper = new ObjectMapper();
@BeforeEach
public void setup() {
openMocks = MockitoAnnotations.openMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(AuthController.class).build();
}
@Test
@DisplayName("로컬 회원 가입 테스트")
public void saveTest() throws Exception
{
// given
user = User.builder()
.userName("minchoi")
.passwd("1234")
.providerType(ProviderType.LOCAL)
.roleType(RoleType.USER)
.build();
// when & then
mockMvc.perform(MockMvcRequestBuilders
.post("/api/v1/auth/save")
.content(objectMapper.writeValueAsString(user))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
}
}
우선 @AutoConfigureMockMvc
와 @WebMvcTest
중에 고민을 했는데 친구가 회사에서 사용한다는 테스트 코드 훔쳐보니까 @AutoConfigureMockMvc
을 사용하고 있어서 일단 사용해봤다. 차이점은 더 알아보자.
파라미터 설정
params vs content
get 으로 보낼 때는 params로 붙여서 보내고
body에 집어넣어서 보낼 때는 content로 붙여서 json으로 보낸다.
@WebMvcTest
- Http server를 실행하지 않고 테스트가 가능
- 웹 상에서의 요청과 응답에 대한 테스트를 할 수 있음
- 모든 설정 정보가 로드 되는 것이 아니기 때문에 조금 가볍다.
- 많은 어노테이션들 (ex: Spring Security, @AutoConfigureWebMvc 등) 다른 설정을 포함하기 때문에 테스트를 용이하게 한다.
@Controller
,@RestController
가 설정된 클래스를 찾아 메모리에 생성한다.
@ActiveProfiles
- dev 설정 파일을 로드한다 (?)
Author And Source
이 문제에 관하여(Springboot Controller 테스트 해보기 1탄 (Mock, MockMvc)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@minchoi/Springboot-Controller-테스트-해보기-1탄저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)