@Mock
- MockBean이라는 것은 Spring Context가 작동되어야 수행할 수 있다.
- 스프링을 쓰지 않고 순수 자바 (단위테스트)에서도 Mock 개념을 사용해야할 수 있다.!
class MailServiceTest {
@DisplayName("메일 전송 테스트")
@Test
void sendMail() {
// given
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);
// when
boolean result = mailService.sendMail("", "", "", "");
// then
assertThat(result).isTrue();
verify(mailSendHistoryRepository, times(1)).save(any(MailSendHistory.class));
}
}
- 가짜의 Mock 객체 두개를 만들고
- MailService 객체에 생성자로 Mock객체를 넣어 MailService를 만들어 주고
- MailService에 대한 stubbing을 진행해준다.
- MailSendClient에서 true를 반환하게
Mock객체의 withSettings();
public static <T> T mock(Class<T> classToMock) {
return mock(classToMock, withSettings());
}
public static MockSettings withSettings() {
return new MockSettingsImpl().defaultAnswer(RETURNS_DEFAULTS);
}
public static final Answer<Object> RETURNS_DEFAULTS = Answers.RETURNS_DEFAULTS;
- int -> zero return
- null -> null return
- collection -> empty
- 형태의 반환 값을 가지게 하는 정책
@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.builder()
.fromEmail(fromEmail)
.toEmail(toEmail)
.subject(subject)
.content(content)
.build()
);
return true;
}
return false;
}
}
- 이걸 테스트 하는 코드가 맨 위에 작동되었을 때 mailSendHistoryRepository의 save는 stubbing 처리를 해주지 않았다.
- Debugging을 수행하면?
- 확인할 수 있다.
Mockito.verify()
- mailSendHistoryRepository에서 save가 1번 호출되는지 확인하는 (행위를 테스트하는데 초점)
리팩토링
- Mock어노테이션을 이용해 Mock객체를 만들고
- @ExtendWith(MockitoExtension.class)를 통해 테스트를 할 때 Mockito를 사용해서 Mock 만들꺼야 인지
- @InjectMocks: MailService의 생성자로 Mock객체가 들어간다.!
@Spy
- 행위에 대한 기록을 하는 객체(Mockito의 verify랑 비슷하지만 다르다!)
- 구현코드
- https://github.com/beginner0107/cafekiosk/commit/6edbdc433abc5ede275102d07afa350fb39f9887
@Mock - MailService 메일 전송 테스트 Spy 기능 연습 TODO: 삭제 예정 · beginner0107/cafekiosk@6edbdc4
beginner0107 committed Dec 24, 2023
github.com
- sendMail에 여러 메서드가 작동하고 있는데 그 중에 메일 전송 기능만 stubbing으로 감싸고 싶을 때
- Spy 사용하면?
- Mockito의 Spy는 실제 객체를 기반으로 만들어진다.
- 실제 객체를 바탕으로 만들어지기 때문에 stubbing이 되지 않는다.
- 객체에서 일부는 실제 객체의 기능을 쓰고 싶고, 나머지 일부만 Stubbing을 하고 싶을 때 Spy를 사용
- 쓰는 빈도는 적음
- Stubber의 메서드를 쓰자
doReturn(true)
.when(mailSendClient)
.sendEmail(anyString(), anyString(), anyString(), anyString());
- 내가 원하는 메서드인 sendmail을 stubbing하였다
- 나머지 메서드들은 실제 객체 기반으로 작동하였다.
'Spring관련 기술 > 테스트코드' 카테고리의 다른 글
한 눈에 들어오는 Test Fixture 구성하기 (0) | 2023.12.25 |
---|---|
BDD Mockito (0) | 2023.12.24 |
Test Double (0) | 2023.12.24 |
Mockito로 Stubbing하기 (0) | 2023.12.24 |
Presentation Layer 테스트 (2) (0) | 2023.12.22 |