Testing - Mockito, SliceTest

귀찮Lee·2022년 7월 19일
0

Spring

목록 보기
26/30

◎ Mockito

  • Mock

    • ’not real, but intended to be very similar to a real situation, substance etc’
    • 테스트 세계에서의 Mock : 바로 가짜 객체
  • Mock의 필요성

    • 다른 계층과 단절되어 불필요한 과정을 줄일 수 있다.
    • 따라서 특정 계층만을 테스트하기 용이함
  • Mockito

    • Mock 객체로 Mocking을 할 수 있게 해주는 라이브러리 (Spring Framework 자체적으로 지원)
    • 사용법 (Controller 테스트)
    @SpringBootTest
    @AutoConfigureMockMvc
    class MemberControllerMockTest {
        // @Autowired를 통해 Spring Bean에 등록된 객체 중비
        @Autowired private MockMvc mockMvc;
        @Autowired private Gson gson;
    			
        // @MockBean : 가짜 객체를 주입
        @MockBean private MemberService memberService;
        @MockBean private MemberMapper mapper;
    
        @Test
        void postMemberTest() throws Exception {
            // given (조건 구성)
            MemberDto.Post post = new MemberDto.Post("hgd@gmail.com", "홍길동", "010-1234-5678");
    
            Member member = new Member("hgd@gmail.com", "홍길동", "010-1234-5678") // (3)
            member.setStamp(new Stamp());
    
            // Test 하는 도중, Mock 객체로 만든 부분을 사용하는 메서드에서 나오는 결과값을 지정       
            given(mapper.memberPostDtoToMember(Mockito.any(MemberDto.Post.class)))
                    .willReturn(member);
            given(memberService.createMember(Mockito.any(Member.class)))
                    .willReturn(member);
    
            // when, then 부분 생략
            ...
    }

◎ API 계층 테스트 (Controller 부분)

@WebMvcTest(MemberController.class)
@MockBean(JpaMetamodelMappingContext.class)
public class MemberControllerRestDocsTest {
    @Autowired private MockMvc mockMvc;
    @Autowired private Gson gson;
  
    @MockBean private MemberService memberService;
    @MockBean private MemberMapper mapper;
 
    @Test
    public void postMemberTest() throws Exception {
        // given (사용할 객체 및 Mock 세팅)
        MemberDto.Post post = new MemberDto.Post("hgd@gmail.com", "홍길동", "010-1234-5678");
        String content = gson.toJson(post);

        MemberDto.response responseDto =
                new MemberDto.response(1L, "hgd@gmail.com", "홍길동", "010-1234-5678",
                                      Member.MemberStatus.MEMBER_ACTIVE, new Stamp());
  
        given(mapper.memberPostToMember(Mockito.any(MemberDto.Post.class))).willReturn(new Member());
        given(memberService.createMember(Mockito.any(Member.class))).willReturn(new Member());
        given(mapper.memberToMemberResponse(Mockito.any(Member.class))).willReturn(responseDto);

        // when (HTTP 요청을 보냄)
        ResultActions actions =
                mockMvc.perform(
                        post("/v11/members")
                                .accept(MediaType.APPLICATION_JSON)
                                .contentType(MediaType.APPLICATION_JSON)
                                .content(content)
                );
  
        // then (검증)
        actions.andExpect(status().isCreated())
                .andExpect(jsonPath("$.data.email").value(post.getEmail()))
                .andExpect(jsonPath("$.data.name").value(post.getName()))
                .andExpect(jsonPath("$.data.phone").value(post.getPhone()))
                .andReturn()
    }
}
  • 관련 어노테이션

    • @WebMvcTest(Controller.class)

      • Controller를 테스트 하기 위한 전용 애너테이션
      • 괄호 안에는 테스트 대상 Controller 클래스를 지정
    • @MockBean(JpaMetamodelMappingContext.class)

      • JPA에서 사용하는 Bean 들을 Mock 객체로 주입해주는 설정
      • Spring 실행 파일에 @EnableJpaAuditing 을 추가하게 되면, 관련 Bean을 필요로 하기 때문에, Test를 진행하게 될 경우 JpaMetamodelMappingContext 를 주입해주어야 함
    • @SpringBootTest, @AutoConfigureMockMvc

      • 쉽게 이야기하자면, Test 환경에서 실행할 수 있도록 Spring을 가동함
      • Controller 부분을 포함해서 모든 부분을 실행하므로, 위의 두 어노테이션을 대체할 수 있지만 속도가 현저히 느려짐
      • 통합 테스트에 더 적합함

◎ 데이터 액세스 계층 (Repository)

  • 데이터 액세스 계층 테스트 규칙

    • 테스트의 순서는 정해져 있지 않으므로 각 테스트가 독립적이어야 한다.
    • 따라서 DB의 상태를 테스트 케이스 실행 이전으로 되돌려서 깨끗하게 만든다.
    // Repository의 기능을 정상적으로 사용하기 위한 Configuration을 Spring이 자동으로 해줌
    // (Spring Boot의 일부분 기능)
    @DataJpaTest  
    public class MemberRepositoryTest {
        @Autowired
        private MemberRepository memberRepository; // Dependency Injection
    
        @Test
        public void saveMemberTest() {
            // given
            Member member = new Member();
            member.setEmail("hgd@gmail.com");
            member.setName("홍길동");
            member.setPhone("010-1111-2222");
    
            // when
            Member savedMember = memberRepository.save(member);
    
            // then
            assertNotNull(savedMember); // (5-1)
            assertTrue(member.getEmail().equals(savedMember.getEmail()));
            assertTrue(member.getName().equals(savedMember.getName()));
            assertTrue(member.getPhone().equals(savedMember.getPhone()));
        }
    }
  • 관련 어노테이션

    • @DataJpaTest : JPA 환경에서 Repository에 사용하는 객체를 Spring Bean에 추가해줌
    • @JdbcTest : Spring JDBC 환경에서 사용
    • @DataJdbcTest : Spring Data JDBC 환경에서 사용
profile
배운 것은 기록하자! / 오류 지적은 언제나 환영!

0개의 댓글