Mockito

Noah·2022년 7월 24일
1

Application Test Study

목록 보기
3/6

Mockito

  • Mock : 진짜 객체와 비슷하게 동작하지만 프로그래머가 직접 그 객체의 행동을 관리하는 객체
  • Mockito : Mock 객체를 쉽게 만들고 관리하고 검증할 수 있는 방법을 제공
  • 가장 많이 사용되는 Mock Framework 중 하나
  • 사용하는 이유
    • DB 또는 외부 API 사용시 테스트를 진행하기 위해 매번 호출하기는 어렵다.
    • 그렇기에 사용해야하는 부부은 Mock 객체로 만들고 어떻게 동작해야하는지를 직접 코딩하여 지정한다.
    • 직접 만든 Mock 객체를 활용하여 테스트를 진행한다.
      • A라는 결과가 DB(or 외부 API)에서 나오게 만들었기에 X 서비스에서 어떻게 동작하는지를 예측하고 테스트할 수 있다.
  • Mock을 사용해서 Unit Test를 진행할 수 있다.
  • Reference : https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html

Mockito 사용하기

  • Spring Boot 2.2 이상의 버전 프로젝트 생성 시, 기본적으로 Spring-boot-starter-test에서 자동으로 Mockito를 추가해 준다.

    • (그림 넣기)
  • Spring Boot를 사용하지 않을 때, 의존성을 직접 추가하는 방법

    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>3.1.0</version>
        <scope>test</scope>
    </dependency>
    
    
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-junit-jupiter</artifactId>
        <version>3.1.0</version>
        <scope>test</scope>
    </dependency>
  • Mockito core : Mockito가 제공하는 기본적인 기능

  • Mockito-junit-jupiter : junit 테스트에서 Mockito를 연동해서 사용할 수 있도록 하는 확장팩이다

  • Mock을 활용하여 테스트 작성시 알아야 하는 3가지 (아래 내용에서 계속....)

    1. Mock을 만드는 방법
    2. Mock이 어떻게 동작해야 하는지 관리하는 방법
    3. Mock의 행동을 검증하는 방법

Mock을 만드는 방법 - Mock 객체 만들기

  1. Mockito.mock() 메소드로 만드는 방법

        @Test
        @DisplayName("Mock 객체 만들기 - Mockito.mock() 메소드로 만들기")
        void makeMockInstanceByMockitoMethod(){
    
            MemberService memberService = Mockito.mock(MemberService.class);
            StudyRepository studyRepository = Mockito.mock(StudyRepository.class);
    
            StudyService studyService = new StudyService(memberService, studyRepository);
            assertNotNull(studyService);
        }
  2. @Mock 어노테이션으로 만드는 방법

    • JUnit5 extention으로 MockitoExtension 사용

      • @ExtendWith
        • 확장 기능 구현하기
        • @ExtendWith(MockitoExtension.class) : 테스트가 Mockito를 사용한다고 명시
    • 필드에 정의하기

      @ExtendWith(MockitoExtension.class)
      class StudyServiceTest {
      
          @Mock
          MemberService memberService;
      
          @Mock
          StudyRepository studyRepository;
      
          @Test
          @DisplayName("Mock 객체 만들기 - @Mock 사용(필드)")
          void makeMockInstanceByMockAnnoVersionField(){
      
              StudyService studyService = new StudyService(memberService, studyRepository);
              assertNotNull(studyService);
          }
      }
    • 메소드 메개변수로 정의하기

      @ExtendWith(MockitoExtension.class)
      class StudyServiceTest {
      
          @Test
          @DisplayName("Mock 객체 만들기 - @Mock 사용(메소드 매개변수)")
          void makeMockInstanceByMockAnnoVersionParameter(@Mock MemberService memberService,
                                                      @Mock StudyRepository studyRepository){
      
              StudyService studyService = new StudyService(memberService, studyRepository);
              assertNotNull(studyService);
          }
      }

Mock이 어떻게 동작해야 하는지 관리하는 방법 - Mock 객체 Stubbing

  • Stubbing 이란?

    • Mock 객체의 행동을 조작하는 것
      • Return 값이 있는 메소드들은 Null을 반환
        • 단, Optional 타입은 Optional.empty 반환
      • Primitive 타입은 기본 Primitive 값을 반환
      • Collection은 비어있는 Collection 반환
      • void 메소드는 예외를 던지지 않고 그냥 지나간다(아무 일도 발생하지 않음)
  • Mock 객체를 조작해서 할 수 있는 일

    1. 특정한 매개변수를 받은 경우 특정한 값을 리턴하거나 예외를 던지도록 하기

      • 특정한 값 리턴

            @Test
            @DisplayName("UserService 유저 정보 가져오기 - 성공 시")
            void getUserInfoById() {
                //Given
                User user = new User("test1234", "1234", "admin", "test@gmail.com");
                Mockito.when(userRepository.getUserInfoById(1L)).thenReturn(Optional.of(user));
        
                //When
                Optional<User> userInfo = userRepository.getUserInfoById(1L);
                UserInfoResponseDTO userInfoResponseDTO = userInfo.get().toUserInfoResponseDTO();
        
                //Then
                assertEquals("test1234", userInfoResponseDTO.getAccount());
                assertEquals("admin", userInfoResponseDTO.getName());
                assertEquals("test@gmail.com", userInfoResponseDTO.getEmail());
            }
      • 예외 상황 발생

        @Test
            @DisplayName("UserService 유저 정보 가져오기 - RuntimeException 발생시키기")
            void getUserInfoException() {
                //Given
                Mockito.when(userRepository.getUserInfoById(2L)).thenThrow(new RuntimeException());
        
                //When
                //Then
                assertThrows(RuntimeException.class, () -> {
                    userRepository.getUserInfoById(2L);
                });
        
            }
    2. void 메소드 특정 매개변수를 받거나 호출된 경우 예외 발생하기

    3. 메소드가 동일한 매개변수로 여러번 호출될 때 각기 다르게 행동하도록 조작하기

Mock의 행동을 검증하는 방법 - Mock 객체 확인

  • Mock 객체가 어떻게 사용이 되었는지 확인하기
    • 특정 메소드가 특정 매개변수로
      • 몇번 호출 되었는지 확인
      • 최소 한번은 호출 되었는지 확인
      • 아예 호출되지 않았는지 확인
    • 어떤 순서대로 호출했는지
    • 특정 시간 이내로 호출됐는지
    • 특정 시점 이후에 아무 일도 벌어지지 않았는지

Tip! 테스트 코드 작성법

  • Given / When / Then으로 나누어서 작성하자
    • Given : 주어진 상황
    • When : 뭔가를 하면
    • Then : 이럴것이다

텍스트

profile
BackEnd 개발자가 되기 위해 공부중입니다!

0개의 댓글