반응형
가독성을 높이는 습관 - 테스트 코드 (2)
테스트 코드의 딜레마
- 처음 테스트 코드를 작성하려고 할 때 겪게 되는 일
- 테스트 코드를 작성하려고하니, 원하는 테스트를 작성하기가 어려움
- 쉽게 테스트 코드를 만들려면? -> 테스트 가능한 구조로 작성되어 있어야함
- 테스트 가능한 구조를 만들려면? -> 좋은 구조 / 코드가 무엇인지 알아야함
- 좋은 구조 / 코드로 작성되었다면? -> 어떤 테스트를 작성해야 할지 알아야함
무엇을 테스트 해야 할까?
- 성송하는 테스트?
- 파라미터?
- 리턴값?
- 호출되는 함수들?
- private / public 메서드?
- 구체적인 것이 아니라 추상적인 것을 테스트 해야함
데이터(상태) 테스트
//상태 검증
@Test
void test1() {
Something something = new Something();
something.foo();
assertThat(something.getStatus()).isTrue();
}
//파라미터 검증
@Test
void test3() {
Something something = mock(Something.class);
ArgumentCaptor<String> stringArgumentCaptor = ArgumentCaptor.forClass(String.class);
something.foo("hello");
verify(something).foo(stringArgumentCaptor.capture());
String value = stringArgumentCaptor.getValue();
assertThat(value).isEqualTo("hello");
}
행위 테스트
//행위 검증
@Test
void test2() {
Something something = mockito.mock(Something.class);
something.foo();
verify(something).foo();
verity(something, never()).bar();
}
성공하는 테스트
@Test
void test2() {
ProductStock productStock = new ProductStock();
productStock.setStock(0);
assertThat(productStock.isSale()).isFalse();
}
실패하는 테스트
@Test
void test2() {
ProductStock productStock = new ProductStock();
productStock.setStock(0);
assertThatThroenBy(() -> productStock.decreaseStock(10))
.isInstanceOf(RuntimeException.class);
}
테스트하기 어려운 것 - 시간
public PaymentResult payment(Order order) {
return isPeperoDay(LocalDateTime.now()) ?
asyncPaymentsService.payments(order) : paymentsService.payements(order);
}
public PaymentResult payment(Order order, LocalDate targetDt) {
return isPeperoDay(targetDt) ?
asyncPaymentsService.payments(order) : paymentsService.payements(order);
}
테스트하기 어려운 것 - private method
private void order(User user, long bookId) {
Book book = findBook(bookId);
UserInfo userInfo = findUserInfo(user);
BookStock bookStock = findBookStock(bookId);
chackOnSale(book);
checkDormant(userInfo);
checkEnoughAge(book, userInfo);
checkEnoughStock(bookStock);
bookStock.decreaseStock();
bookStockRepository.save(bookStock);
bookOrderRepository.save(createBookOrder(user, book));
}
Q. private 메소드는 어떻게 테스트 해야하나요?
어떻게든 private 메소드를 테스트하고 싶다면, 그 메소드는 결코 private이면 안된다.
public으로 바꿔도 될지 마음에 걸린다면, 이 메소드는 별도의 책임의 일부로서 원래는 다른 클래스에 들어있어야 한다.
- 마이클 C. 페더스 - Working effectivel\y with legacy code 중
테스트하기 어려운 것 - 확률
Random random = new Random();
- Random은 통계를 기반으로한 확률로 테스트할 수밖에 없음
테스트하기 어려운 것 - 자동 생성되는 코드들
- Swager-autogen을 통해 만들어진 클래스들
- QueryDSL을 사용하기 위해 만들어진 Qclass
- Lombok으로 자동 생성되는 코드들 (Bytecode Instrumentation)
정리
- 테스트 코드의 딜레마
- 테스트 대상 (상태 vs 행위)
- 성공 테스트와 실패 테스트
- 테스트하기 어려운 요소들
- 시간
- private method
- 확률
- 자동 생성 코드들
반응형
'cs > java-spring-boot' 카테고리의 다른 글
[Zero-base] 12-1. 현업에서 마주하는 실제 요청은? (0) | 2022.03.22 |
---|---|
[Zero-base] 10-5. 테스트 코드 (3) - 실습 (0) | 2022.03.19 |
[Zero-base] 10-3. 테스트 코드 (1) (0) | 2022.03.18 |
[Zero-base] 10-2. 익셉션 핸들링 (2) - 실습 (0) | 2022.03.18 |
[Zero-base] 10-1. 익셉션 핸들링 (1) (0) | 2022.03.18 |