5.1 목과 스텁 구분
5.1.1 테스트 대역 유형
목은 외부로 나가는 상호 작용을 모방하고 검사하는 데 도움이 된다. 이러한 상호 작용은 SUT가 상태를 변경하기 위한 의존성을 호출하는 것에 해당한다.
스텁은 내부로 들어오는 상호 작용을 모방하는 데 도움이 된다. 이러한 상호 작용은 SUT가 입력 데이터를 얻기 위한 의존성을 호출하는 것에 해당한다
5.1.2 도구로서의 목과 테스트 대역으로서의 목
class ControllerTest { @Mock private IEmailGateway emailGateway; // mock 생성 @Mock private IDatabase database; // mock 생성 @Test public void sending_a_greetings_email() { // given Controller sut = new Controller(emailGateway, database); // when sut.greetUser("user@gamil.com"); // then then(emailGateway) .should(times(1)) .sendGreetingEmail("user@email.com"); // 테스트 대역으로 하는 SUT의 호출을 검사 } @Test public void creating_a_report() { // given given(database.getNumberOfUsers()).willReturn(10); // stub 생성 Controller sut = new Controller(emailGateway, database); // when Report report = sut.createReport(); // then assertThat(10).isEqualTo(report.getNumberOfUsers()); }
}
### 5.1.3 스텁으로 상호 작용을 검증하지 말라
- SUT에서 스텁으로의 호출은 SUT가 생성하는 최종 결과가 아니라 최종 결과를 산출하기 위한 수단일 뿐이다.
> 스텁과의 상호 작용을 검증하는 것은 취약한 테스트를 야기하는 일반적인 안티 패턴이다.
### 5.1.4 목과 스텁 함께 쓰기
```java
@Test
public void purchase_fails_when_not_enough_inventory() {
// given
Store storeMock = mock(Store.class);
given(storeMock.hasEnoughInventory(Product.SHAMPOO, 5)).willReturn(false); // 준비된 응답을 설정
Customer sut = new Customer();
// when
boolean success = sut.purchase(storeMock, Product.SHAMPOO, 5);
// then
assertThat(success).isFalse();
then(storeMock).should(times(0)).removeInventory(Product.SHAMPOO, 5); // SUT에서 수행한 호출을 검사
}
5.1.5 목과 스텁은 명령과 조회에 어떻게 관려돼 있는가?
- CQS(Command Query Separation)원칙에 따르면 모든 메서드는 명령이거나 조회여야 하며, 이 둘을 혼용해서는 안 된다.
- 메서드가 사이드 이펙트를 일으키면 해당 메서드의 반환타입이 void인지 확인하라. 그리고 메서드가 값을 반환하면 사이드 이펙트가 없어야 한다.
- 가능한한 CQS원칙을 따라라.
5.2 식별할 수 있는 동작과 구현 세부 사항
- 테스트 코드와 코드의 구현 세부사항의 강결합을 피하는 방법은 코드가 생성하는 최종 결과(식별할 수 있는 동작)를 검증하고 구현 세부 사항과 테스트를 가능한 한 떨어뜨리는 것뿐이다.
- 구현 세부 사항을 숨기면 클라이언트의 시야에서 클래스 내부를 가릴 수 있기 때문에 내부를 손상시킬 위험이 적다.
- 데이터와 연산을 결합하면 해당 연산이 클래스의 불변성을 위반하지 않도록 할 수 있다.
- 모든 구현 세부 사항을 비공개로 하면 테스트가 식별할 수 있는 동작을 검증하는 것 외에는 다른 선택지가 없으며, 이로 인해 리팩터링 내성도 자동으로 좋아진다.
참고
'개발관련 서적 정리 > Unit Testing' 카테고리의 다른 글
7. 가치 있는 단위 테스트를 위한 리팩터링 (0) | 2023.02.11 |
---|---|
6. 단위 테스트 스타일 (0) | 2023.02.08 |
4. 좋은 단위 테스트의 4대 요소 (0) | 2023.02.05 |
3. 단위 테스트 구조 (1) | 2023.02.05 |
2. 단위 테스트란 무엇인가 (1) | 2023.02.05 |