티스토리 뷰

 

Mockito와 BDDMockito 둘 다 Java 기반의 테스트 프레임워크로, 모킹(mocking)을 지원한다. 이 둘은 기능상에 차이점은 없으나, 모킹하는 스타일 방식이 차이가 있다.

1. Mockito를 통해 Mock 객체 생성하는 방법

@Mock 애너테이션을 통해 Mock 객체를 생성하고, @InjectMocks 애너테이션을 통해 Mock 객체를 주입할 수 있다. 예를 들어, MailService 객체를 생성하기 위해서 MailSendClient와 MailSendHistoryRepository가 필요하다. 이를 위해 @Mock 애너테이션을 사용하여 MailSendClient와 MailSendHistoryRepository 클래스의 Mock 객체를 생성하고, @InjectMocks 애너테이션을 통해 이 Mock 객체들을 MailService에 주입할 수 있다.

@ExtendWith(MockitoExtension.class)
class MailServiceTest {

    @Mock
    private MailSendClient mailSendClient;

    @Mock
    private MailSendHistoryRepository mailSendHistoryRepository;

    @InjectMocks
    private MailService mailService;

}

 

 

2. 행위 주도 개발(BDD, Behavior-Driven Development)

BDD란 행위 주도 개발이라고 불리며, TDD에서 착안한 방법론이다. TDD에서 발전된 개념으로, 사용자 요구사항에 맞춘 시스템의 행동에 초점을 맞춰 개발 및 테스트 과정을 진행한다.

2-1. BDD의 특징

  • BDD는 사용자가 어떻게 사용할 것인가에 중점을 둔다. 즉, 시스템이 특정 입력을 받으면 어떤 행동을 해야 하는지를 작성한다.
  • Given-When-Then 패턴 : BDD에서는 테스트 시나리오는 Given-When-Then 구조로 작성한다.
    • Given : 어떤 초기 상태가 주어졌을 때 (테스트 전제 조건)
    • When : 특정 행동이 일어났을 때 (테스트 대상 동작)
    • Then : 기대하는 결과가 나와야 한다. ( 테스트 결과 검증)

2-2. Given-When-Then 예시

  • given : sendEmail() 메서드가 호출되었을 때, 해당 메서드는 true를 반환하도록 설정한다.
    • anyString() : 어떤 문자열이 들어와도 상관없다.
  • when : sendMail() 메서드를 호출한다.
  • then : sendMail() 메서드가 호출되었을 때, 그 결과는 true여야 한다.
@ExtendWith(MockitoExtension.class)
class MailServiceTest {

    @Mock
    private MailSendClient mailSendClient;

    @Mock
    private MailSendHistoryRepository mailSendHistoryRepository;

    @InjectMocks
    private MailService mailService;

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

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

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

}
@RequiredArgsConstructor
@Service
public class MailService {

    private final MailSendClient mailSendClient;
    private final MailSendHistoryRepository mailSendHistoryRepository;

    public boolean sendMail(String fromEmail, String toEmail, String subject, String content) {
        boolean result = mailSendClient.sendEmail(fromEmail, toEmail, subject, content);
        if (result) {
            mailSendHistoryRepository.save(
                MailSendHistory.create(fromEmail, toEmail, subject, content)
            );
            return true;
        }
        return false;
    }
}

 

3. Mockito를 사용하는 테스트 코드의 어색함

테스트 코드를 작성할 때, BDD 형식에 맞추어 작성하기 위해 Given-When-Then 절을 사용하였다. 그러나 아래 코드를 보면 when() 메서드를 사용하여 테스트 전제 조건을 설정하고 있다. 전제 조건을 설정하는 것이므로 given 절에 위치하는 것이 맞지만, when() 메서드와 given 절 사이에서 어색함이 발생한다.

Mockito의 when() 메서드는 TDD 패턴에 맞춰진 방식으로, BDD 스타일의 Given-When-Then 패턴과는 약간의 차이가 발생한다.

@ExtendWith(MockitoExtension.class)
class MailServiceTest {

    @Mock
    private MailSendClient mailSendClient;

    @Mock
    private MailSendHistoryRepository mailSendHistoryRepository;

    @InjectMocks
    private MailService mailService;

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

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

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

}

 

4. BDDMockito를 사용하여 BDD 스타일에 맞춰 테스트 코드 작성하기

BDDMockitoMockito를 상속받아 BDD 스타일의 테스트 작성을 지원한다. BDDMockito는 Mockito와 동일한 기능을 제공하면서도 Given-When-Then 패턴을 직관적으로 사용할 수 있도록 설계되었다. 따라서 Mockito 기능을 기반으로 BDD 패턴에 맞는 표현을 사용하여 더 직관적인 테스트 코드 작성을 돕는다.

  • Mockito : when().thenReturn()
  • BDDMockito : given().willReturn()
@ExtendWith(MockitoExtension.class)
class MailServiceTest {

    @Mock
    private MailSendClient mailSendClient;

    @Mock
    private MailSendHistoryRepository mailSendHistoryRepository;

    @InjectMocks
    private MailService mailService;

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

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

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

}

 

5. 결론

Mockito와 BDDMockito 둘 다 모킹 기능을 제공하지만, BDD 패턴에 맞추어 테스트 코드를 작성할 때 Mockito를 사용하는 경우 약간의 어색함이 발생한다. 이는 when() 메서드를 Given 절에 사용하는 것이 BDD 흐름과 맞지 않기 때문이다.

따라서 BDDMockito를 사용하여 Given-When-Then 구조에 맞춰 더 직관적이고 자연스러운 테스트 코드 작성이 가능하다.

Total
Today
Yesterday
최근에 올라온 글
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30