@Mock, @Spy, @InjectMocks

qkdk·2024년 2월 5일
0

TDD

목록 보기
9/12

Mock객체인 MailSendClient의 Stubbing을 해주지 않았는데 리턴값은 어떻게 될까?

class MailServiceTest {

    @DisplayName("메일 전송 테스트")
    @Test
    void sendMail() {
        MailSendClient mailSendClient = mock(MailSendClient.class);
        MailSendHistoryRepository mailSendHistoryRepository = mock(MailSendHistoryRepository.class);

        MailService mailService = new MailService(mailSendClient, mailSendHistoryRepository);

//        when(mailSendClient.sendEmail(anyString(), anyString(), anyString(), anyString()))
//            .thenReturn(true);

        boolean result = mailService.sendMail("", "", "", "");

        assertThat(result).isTrue();
    }

}

예상 반환타입인 boolean의 default(false) 값을 리턴한다.

  • Primitive 타입인 경우 Primitive타입의 기본값을 리턴
  • 인스턴스로 반환하는 경우는 null을 기본으로 리턴한다.

Mock객체의 동작 검증하기

class MailServiceTest {

    @DisplayName("메일 전송 테스트")
    @Test
    void sendMail() {
        MailSendClient mailSendClient = mock(MailSendClient.class);
        MailSendHistoryRepository mailSendHistoryRepository = mock(MailSendHistoryRepository.class);

        MailService mailService = new MailService(mailSendClient, mailSendHistoryRepository);

        when(mailSendClient.sendEmail(anyString(), anyString(), anyString(), anyString()))
            .thenReturn(true);


        boolean result = mailService.sendMail("", "", "", "");

        assertThat(result).isTrue();
        Mockito.verify(mailSendHistoryRepository, times(1)).save(any(MailSendHistory.class));
    }

}

Mockito의 verify를 이용해 검증을 진행할 수 있다.

@Mock,@ExtendWith(MockitoExtension.class)

@ExtendWith(MockitoExtension.class)
class MailServiceTest {

    @Mock
    private MailSendClient mailSendClient;

    @Mock
    private  MailSendHistoryRepository mailSendHistoryRepository;

    @DisplayName("메일 전송 테스트")
    @Test
    void sendMail() {
        MailService mailService = new MailService(mailSendClient, mailSendHistoryRepository);

        when(mailSendClient.sendEmail(anyString(), anyString(), anyString(), anyString()))
            .thenReturn(true);

        boolean result = mailService.sendMail("", "", "", "");

        assertThat(result).isTrue();
        Mockito.verify(mailSendHistoryRepository, times(1)).save(any(MailSendHistory.class));
    }
}
  • Mockito.mock()으로 객체를 생성하던 작업을 @Mock annotation을 이용하여 진행할 수 있다.
    • 단 테스트 클래스 위에 ExtendWith(MockitoExtension.class) 가 필요하다.

@InjectMocks

@ExtendWith(MockitoExtension.class)
class MailServiceTest {

    @Mock
    private MailSendClient mailSendClient;

    @Mock
    private MailSendHistoryRepository mailSendHistoryRepository;

    @InjectMocks
    private MailService mailService;

    @DisplayName("메일 전송 테스트")
    @Test
    void sendMail() {
        when(mailSendClient.sendEmail(anyString(), anyString(), anyString(),
            anyString())).thenReturn(true);

        boolean result = mailService.sendMail("", "", "", "");

        assertThat(result).isTrue();
        Mockito.verify(mailSendHistoryRepository, times(1)).save(any(MailSendHistory.class));
    }
}
  • DI 와 똑같이 InjectMocks로 지정된 클래스의 생성자를 보고 의존성 주입을 진행해준다.

@Spy

Mock되는 대상의 기능이 많아 일부는 실제 객체의 동작을, 일부는 Stubbing을 통한 동작을 진행하고 싶을때 사용한다.

@Slf4j
@Component
public class MailSendClient {

    public boolean sendEmail(String fromEmail, String toEmail, String subject, String content) {
        log.info("메일 전송");
        throw new IllegalArgumentException("메일 전송");
    }

    public void a() {
        log.info("a");
    }

    public void b() {
        log.info("b");
    }

    public void c() {
        log.info("c");
    }

}

예를 들어 위의 코드에서 sendMail만 Stubbing하고, 나머지 메서드는 직접 사용하고 싶을때

  • Mock객채로 만들며는 a,b,c의 로그가 찍히지 않는다.
@ExtendWith(MockitoExtension.class)
class MailServiceTest {

    @Spy
    private MailSendClient mailSendClient;

    @Mock
    private MailSendHistoryRepository mailSendHistoryRepository;

    @InjectMocks
    private MailService mailService;

    @DisplayName("메일 전송 테스트")
    @Test
    void sendMail() {
//        when(mailSendClient.sendEmail(anyString(), anyString(), anyString(),
//            anyString())).thenReturn(true);

        doReturn(true)
            .when(mailSendClient)
            .sendEmail(anyString(), anyString(), anyString(), anyString());

        boolean result = mailService.sendMail("", "", "", "");

        assertThat(result).isTrue();
        Mockito.verify(mailSendHistoryRepository, times(1)).save(any(MailSendHistory.class));
    }
}

유의 사항

  • 실제 객체를 기반으로 생성이 되기 때문에 Stubbing이 되지 않는다.
  • 다른 문법을 사용해야 한다.
profile
qkdk

0개의 댓글

관련 채용 정보