@DisplayName("특정 날짜로 결제완료 주문들을 조회하여 매출 통계 메일을 전송한다.")
@Test
void sendOrderMail() {
// given
// 결제 완료 주문 정보를 생성/저장한다.
// stubbing
Mockito.when(mailSendClient.sendMail(anyString(), anyString(), anyString())
.thenReturn(true);
// when
boolean result = orderService.sendOrderMail(LocalDate.of(2025,3,27), "manager@test.com");
// then
assertThat(result).isTrue();
List<MailSendHistory> histories = mailSendHistoryRepository.findAll();
assertThat(histories).hasSize(1)
.extracting("content")
.contains("검색 일자의 매출 합계는 3000원입니다.")
;
}
아주 이해하기 쉬운 Mockito 덕분에, 테스트 코드에서 스터빙을 이해하기는 쉽다.
"어떤 값이 오든! 해당 메서드의 응답은 true를 반환해라!"
테스트를 위해서 매번 메일 사용비를 지출할 수는 없다.
마치 메일 API처럼 있지만, 그냥 지정된 응답값만 반환하는 가짜 메일 오브젝트가 생겼다.
외부 서비스의 응답값을 스터빙한 덕분에,
목적이었던 sendOrderMail 메서드에 집중할 수 있다.
이제 Mockito를 활용한 테스트에서 말하는 Stub을 정리해 볼 수 있겠다.
Stub : 지정된 상황에 고정된 응답값을 반환하는 가짜 객체 또는 그런 행위
내가 처음 들어본 Stub
정보처리기사를 공부해 봤다면 아래 내용을 알고 있을 것이다. (정보처리기사는 흥달쌤!)
V model
통합 테스트는 상향식, 하향식, 빅뱅, 백본 테스트로 나눈다. 테스트 장치 도구(Test Harness)로는 드라이버, 스텁, 목 오브젝트.. 등이 있다. - 상향식 테스트 (Bottom-up) : 상위 모듈이 미개발되었다면 '드라이버'를 사용한다. - 하향식 테스트 (Top-down) : 하위 모듈이 미개발되었다면 '스텁'을 사용한다.
테스트 코드에서 사용하는 방식을 보면
결국 가짜 객체를 말하는 걸 텐데..
그럼 드라이버는 뭐지..?
What is the difference between stubs and drivers in software testing? (원본링크)
Stubs - Definition: A stub is a simplified implementation of a module or component that a module under test depends on. It simulates the behavior of the missing component by providing predetermined responses to calls made during the test. Drivers - Definition: A driver is a program or component that invokes a module or component under test. It simulates the higher-level calling environment, providing input and controlling the execution flow. (...)
배우와 외모, 체형마저 닮아 위험한 액션 외에 간단한 연기도 하는 이들을 스턴트 더블이라고 부른다.
(참고, 슬랭처럼 그냥 Mock이라고 말하는 것도 Test Double과 동일한 의미를 가지기도 한다.)
위에서 본 것처럼 배우인 MailClient를 대신해서 연기하는 가짜 MailClient를 칭한다.
우리는 위험한 테스트를 위해서 가짜 객체를 사용할 것이다. (표현하자면)
언제 어떻게 사용하느냐에 따라 테스트 더블의 명칭이 달라진다.
출처 http://xunitpatterns.com/Test%20Double.html
테스트 더블 (Test Double) - 더미 (Dummy) : 아무런 동작도 하지 않는 인스턴스이다. - 스텁 (Stub) : 테스트에 맞도록 의도한 응답을 반환한다. - 스파이 (Spy) : Stub과 유사하지만 스스로 호출된 내역을 기록한다. - 목 (Mock) : Stub과 유사하지만 예상 값으로 프로그래밍되어있다. Stub과 달리 예외가 발생할 수 있다. - 페이크 (Fake) : 실제 동작하는 객체이지만 제품에는 사용할 수 없는 임시 객체이다.
Dummy
말 그대로 가짜이다. 아무런 기능을 할 수 없고 파라미터를 채우기 위한 용도가 될 수 있다.
Stub
의도한 응답을 반환하도록 단순하게 처리된 인스턴스이다.
테스트의 목적대로 동작하기 때문에 예외가 발생할 수 없다.
주로 테스트 중인 클래스에 데이터를 제공하기 위해 사용한다.
Spy
Stub과 매우 유사하게 동작한다. 단 호출될 때마다 호출 내역을 기록한다. (마치 잠입한 감시자처럼)
void 반환을 가진 기능을 검사한다면 활용할 수 있다.
(**Mockito내에 Spy 어노테이션이 있다. 이것은 테스트 더블의 스파이와는 다른 것이다!)
Mock
상호작용을 검사하기 위한 일종의 Stub이다. 자신이 할 기능까지 알고 있다는 점에서 Spy보다 발전된 임시 객체다.
Mock은 인스턴스 연관관계에 따라서 응답하기 때문에 예외가 발생할 수 있다.
테스트 중이 클래스에 의해 호출되고 동작 결과를 확인할 수 있다.
데이터와 구현 모두를 제공한다는 부분이 Stub과의 차이이다.
Fake
이것은 Stub이 아니다! 진짜 실제 동작하는 객체이다. 하지만 제품에는 사용할 수 없다.
시뮬레이션과 같이 진짜 세상에 나가기 전 다른 가상 환경을 검사하는 것으로 비유할 수 있다.