@WebMvcTest, @AutoConfigureMockMvc @DataJpaTest

Seung jun Cha·2022년 7월 26일

1. @WebMvcTest

  • @SpringBootTest의 경우 모든 빈을 로드하기 때문에 테스트 구동 시간이 오래 걸리고, 테스트 단위가 크기 때문에 디버깅이 어려울 수 있다. Controller 레이어만 슬라이스 테스트 하고 싶을 때에는 @WebMvcTest를 쓰는게 유용하다.

  • 웹에서 테스트하기 힘든 컨트롤러를 테스트 하는데 적합

  • @WebMvcTest는 @SpringBootTest와 같이 사용될 수 없다. 왜냐하면 각자 서로의 MockMvc를 모킹하기 때문에 충돌이 발생하기 때문이다.

2. @AutoConfigureMockMvc

  • @SpringBootTest와 함께 사용되어 테스트 환경을 구성합니다. @AutoConfigureMockMvc를 사용하면 애플리케이션 컨텍스트가 로드되고 MockMvc 인스턴스가 자동으로 구성됩니다.
  • 컨트롤러 뿐만아니라 테스트 대상이 아닌 @Service나 @Repository가 붙은 객체들도 모두 메모리에 올린다.
    (전체 애플리케이션 구성을 로드하고 MockMVC를 사용하려는 경우..?)

3. @DataJpaTest

  • JPA에 관련된 요소들만 테스트하기 위한 어노테이션으로 JPA 테스트에 관련된 설정들만 적용해준다.

  • 메모리상에 내부 데이터베이스를 생성하고 @Entity가 선언된 클래스를 스캔하여 repository를 구성한다. @Transactional을 기본적으로 내장하고 있으므로, 각 테스트마다 테스트가 완료되면 관련한 설정들은 롤백된다. repository 테스트를 위해 사용

4. Service 단위테스트

@ExtendWith(MockitoExtension.class)
class MemberServiceTest {

    @Mock
    private MemberRepository memberRepository;

    @Mock
    private Member member;
    
    @Mock
    private PasswordEncoder passwordEncoder;

    @InjectMocks
    private MemberService memberService;


    private Member createMember(){
        MemberFormDto memberFormDto = new MemberFormDto();
        memberFormDto.setAddress("address");
        memberFormDto.setEmail("aaa@aaa.com");
        memberFormDto.setName("name");
        memberFormDto.setPassword("1111");
        
        return Member.createMember(memberFormDto, passwordEncoder);
    }

4. MockMVC

  • MockMvc는 웹 어플리케이션을 애플리케이션 서버에 배포하지 않고, 실제 서블릿 컨테이너를 사용하지 않고 테스트용 MVC환경을 만들어 요청 및 전송, 응답기능을 제공해주는 유틸리티 클래스다.

2-1 MockMVC 주입방법

  1. @SpringBootTest + @AutoConfigureMockMvc : MockMVC를 이용하여 통합테스트를 할 때 사용
  2. @WebMvcTest : MVC쪽만 슬라이스(slice) 테스트를 할 때 사용

2-2 MockMVC 사용방법

  • @WithMockUser
    @WithMockUser에서 생성한 사용자 이름, 패스워드, 권한으로 UserDetails을 생성한 후 보안 컨텍스트를 로드합니다
    (@WithMockUser 유저로 가짜 로그인을 한 상태로 만듬)

1. 요청 메서드

  • MockMvcRequestBuilders
    파일이 관련되어 있다면 MockMultipartHttpServletRequestBuilder

    (1) aram / params : 쿼리 스트링 설정

    (2) cookie : 쿠키 설정

    (3) requestAttr : 요청 스코프 객체 설정

    (4) sessionAttr : 세션 스코프 객체 설정

    (5) content : 요청 본문 설정

    (6) header / headers : 요청 헤더 설정

    (7) contentType : 본문 타입 설정

    (8)get, post : url 전송방식

    public MockHttpServletRequestBuilder MockMvcRequestBuilder
    (String url, MediaType mediaType, Map usernamePasswordMap) 
    throws JsonProcessingException {
          
          return MockMvcRequestBuilders.post(url)
          .contentType(mediaType)
          .content(objectMapper.writeValueAsString(usernamePasswordMap));
      }
      
       public ResultActions perform2
       (String url, MediaType mediaType, Map usernamePasswordMap) 
       throws Exception {
          return mockMvc.perform(MockMvcRequestBuilder(
          LOGIN_URL,
          MediaType.APPLICATION_JSON, 
          usernamePasswordMap
          ));
      }

2. 검증 메서드

  • andExpect()
    실행 결과를 검증할 때는 ResultActions를 이용하여 andExpect 메서드를 사용

(1)status : 상태 코드 검증

(2)header : 응답 header 검증

(3)content : 응답 본문 검증

(4)cookie : 쿠키 상태 검증

(5)view : 컨트롤러가 반환한 뷰 이름 검증

(6)redirectedUrl(Pattern) : 리다이렉트 대상의 경로 검증

(7)model : 스프링 MVC 모델 상태 검증

(8)request : 세션 스코프, 비동기 처리, 요청 스코프 상태 검증

(9)forwardedUrl : 이동대상의 경로 검증

 public ResultActions perform(String url, MediaType mediaType, 
 Map usernamePasswordMap) throws Exception {
        
        return mockMvc.perform(MockMvcRequestBuilders.
                post(url)
                .contentType(mediaType)
                .content(objectMapper.writeValueAsString(usernamePasswordMap))); 
                // map타입이 String타입의 JSON으로 변환된다
    }
    
    @Test
    @DisplayName("login_success")
    void loginSuccess() throws Exception {
        //given
        Map usernamePasswordMap = getUsernamePasswordMap(USERNAME, PASSWORD);
        //when
        perform(LOGIN_URL, MediaType.APPLICATION_JSON, usernamePasswordMap)
                .andDo(print())
                .andExpect(status().isOk())
                .andReturn();

    } 

3. 기타 메서드

(1)andDo() : print, log를 사용할 수 있는 메소드

(2)print() : 실행결과를 지정해준 대상으로 출력, default = System.out

(3)log() : 실행결과를 디버깅 레벨로 출력, 레벨은 org.springframework.test.web.servlet.result

(4)스테틱 메서드
1. MockMvcRequestBuilders 요청 데이터를 설정할 때 사용

  private ResultActions perform(String url, MediaType mediaType, Map usernamePasswordMap) throws Exception {
        return mockMvc.perform(MockMvcRequestBuilders
                .post(url)
                .contentType(mediaType)
                .content(objectMapper.writeValueAsString(usernamePasswordMap)));
  • writeValueAsString : map타입이 String타입의 JSON으로 변환됨
    {age = 10} => {"age" : "10"}
  1. MockMvcResultMatchers 실행 결과를 검증할 때 사용
  2. MockMvcResultHandlers 실행 결과를 로그 등으로 출력할 때 사용할 static 메서드

0개의 댓글