Mock, Mockito

hsso_o·2024년 7월 18일
0

스터디

목록 보기
30/44

Mock 테스트

  • 실제 객체 대신 가짜 객체(Mock)를 사용하여 테스트를 수행하는 방법
  • 실제 객체와 동일한 모의 객체를 만들어 테스트의 효용성을 높이기 위해 사용
  • 테스트 환경에서 의존성 문제를 해결하고, 독립적인 단위 테스트 수행 가능

주요 특징

  • 독립적인 단위 테스트 : 외부 의존성 없이 독립적으로 테스트 가능
    • 신뢰성, 안정성 ↑
  • 의존성 분리 : 외부 의존성을 실제로 호출하지 않고, Mock 객체로 대체하여 테스트
    • 테스트 속도 ↑, 외부 시스템 상태에 따라 테스트 결과가 달라지는 문제 해결
  • 정확한 시나리오 제어 : 특정 상황이나 에러조건 시뮬레이션이 쉬움
    • 다양한 시나리오에 대한 테스트 가능

테스트 더블

  • 소프트웨어 테스트에서 실제 객체를 대체하여 사용되는 가상 객체들
  • 테스트 작성 단순화 및 의존성 관리에 사용
테스트 더블 종류설명
Mock 객체실제 객체를 대체하여 가상의 동작을 정의하는 객체
Stub고정된 입력에 대해 고정된 출력을 반환하는 간단한 구현
Fake실제 구현과 유사하게 동작하지만 단순화된 형태의 구현
Spy실제 객체의 일부 기능을 모방하며, 다른 기능은 실제 객체를 사용하는 객체
Dummy테스트 중에 사용되지 않는 객체로, 인터페이스를 구현하여 필수 인자로 사용될 때 대체하는 객체

Mockito

  • Java 애플리케이션에서 테스트를 위해 널리 사용되는 Mocking 프레임워크

관련 어노테이션

@Mock

  • Mock 객체 생성
  • 실제 객체의 동작을 흉내내지만 내부 로직은 수행X
    • 모든 메서드가 Mocking → 실제 로직 실행되지 않음
  • 주로 테스트에서 외부 의존성을 대체하여 독립적인 테스트를 수행하기 위해 사용

@Spy

  • 실제 객체의 메서드를 호출하며 필요에 따라 특정 메서드만 Mocking 가능
    • 실제 객체의 메서드 호출 → 실제 로직 실행
    • 특정 메서드만 Mocking → 특정 메서드만 다른 동작 수행 가능
  • 기존 객체의 동작을 유지하면서 일부 메서드의 동작을 변경할 때 사용
    • @Spy로 만든 mock 객체는 진짜 객체이며, 메소드 실행 시 스터빙을 하지 않으면 기존 객체의 로직을 실행한 값을, 스터빙을 한 경우엔 스터빙 값을 리턴

      public class SpyExampleTest {
      
          @Spy
          private List<String> spyList = new ArrayList<>();
      
          @Test
          public void testSpyList() {
              // 스파이 객체는 실제 객체와 동일하게 동작
              spyList.add("A");
              spyList.add("B");
      
              assertEquals(2, spyList.size());
              assertEquals("A", spyList.get(0));
      
              // 특정 메서드를 Mocking하여 다른 동작을 수행하도록 설정
              when(spyList.size()).thenReturn(100);
      
              assertEquals(100, spyList.size()); // 스파이된 메서드는 Mocking된 동작을 수행
              assertEquals("A", spyList.get(0)); // 나머지 메서드는 원래 동작을 그대로 수행
          }
      }

@InjectMocks

  • Mockito가 생성한 목 객체(Mock)들을 주입받아 테스트할 클래스의 필드에 자동으로 주입
  • 주로 테스트 대상 객체의 의존성을 자동으로 주입하기 위해 사용

스터빙(Stubbing)

  • Mock 객체나 Spy 객체의 특정 메서드 호출 시 반환 값을 설정하는 과정
  • 주요 문법
    문법설명
    when(methodCall).thenReturn(value)특정 메서드 호출 시 지정된 값을 반환하도록 설정
    doReturn(value).when(mock).methodCall()void 메서드 또는 예외를 던지는 메서드를 스터빙할 때 사용

검증(Verify)

  • Mock 객체의 메서드 호출 여부와 호출 횟수를 검증하는 과정
  • 주요 문법
    문법설명
    verify(mock).methodCall()특정 메서드가 호출되었는지 검증
    verify(mock, times(n)).methodCall()특정 메서드가 n번 호출되었는지 검증
    verify(mock, never()).methodCall()특정 메서드가 호출되지 않았는지 검증

구현 방법

  1. Mock 객체 생성

    • Java에서는 Mockito 라이브러리를 사용하여 Mock 객체를 생성(@Mock)
    @Mock
        private UserRepository userRepository;
  2. Mock 객체 설정

    • Mock 객체가 특정 동작을 하도록 설정
    User mockUser = new User("John", "Doe");
    
    // userRepository.findById(1L) 호출 시 mockUser 객체를 반환하도록 설정
    when(userRepository.findById(1L)).thenReturn(Optional.of(mockUser));  // 스터빙
  1. 테스트 수행

    • Mock 객체와 상호작용하는 코드를 호출하고, 예상되는 결과 검증
    @Test
            User user = userService.getUser(1L);
            assertNotNull(user);
            assertEquals("John", user.getFirstName());
  1. 검증

    • Mock 객체가 예상대로 사용되었는지 검증
    verify(userRepository).findById(1L);
  • 전체 코드 및 설명
    import static org.mockito.Mockito.*;
    import static org.junit.Assert.*;
    import org.mockito.Mock;
    import org.mockito.InjectMocks;
    import org.mockito.MockitoAnnotations;
    import org.junit.Before;
    import org.junit.Test;
    import java.util.Optional; 
    
    public class UserServiceTest {
    
        @Mock
        private UserRepository userRepository; // UserRepository의 Mock 객체를 생성
    
        @InjectMocks
        private UserService userService; // UserService 객체를 생성하고 @Mock 객체를 주입
    
        @Before
        public void setup() {
            MockitoAnnotations.openMocks(this); // @Mock 어노테이션이 붙은 객체를 초기화
        }
    
        @Test
        public void testUserService() {
            
            User mockUser = new User("John", "Doe");
            
            // userRepository.findById(1L) 호출 시 mockUser를 반환하도록 설정
            when(userRepository.findById(1L)).thenReturn(mockUser); 
    
            // UserService의 getUser 메서드를 호출 및 반환 값 검증
            // userService 내부에서 userRepository.findById(1L)이 호출되어 mockUser 객체 반환
            User user = userService.getUser(1L);
            assertNotNull(user);
            assertEquals("John", user.getFirstName());
    
            // userRepository.findById(1L) 메서드가 호출되었는지 검증
            verify(userRepository).findById(1L);
        }
    }
    
profile
아뇨 소혠데요-

0개의 댓글