[Java JUnit5] (2) 실전준비. Given - When - Then Patter
바로전 포스트까진 TDD가 무엇이고 JUnit의 기초를 살펴보았다면 이제는 JUnit을 어떻게 사용하는지 알아보도록 하자, 앞으로의 테스트 방식을 Given When Then 패턴을 사용하기 때문에 먼저 이 패턴에 대해서 설명하려 한다.
이포스팅에서 전에 배우지 않은 부분이 있더라도 여기선 Given-When-Then을 어떻게 사용하는지만 익히는 파트이므로 넘어가도록 하자
0. 목차
- Given-When-Then 이란?
- Test
1. Given-When-Then 이란?
Given-When-Then 패턴은 대부분의 개발자가 잘 알고 있는 내용일 것이다. 하지만 막상 Test코드를 작성할때 이러한 원칙을 잘 지키지는 않고 있다. (나또한,,) 필수는 아니지만, 초반엔 잘 지키려 노력해보도록 하자.
본론으로, Given-When-Then 패턴이란 1개의 단위 테스트를 3가지 단계로 나누어 처리하는 패턴으로, 각각의 단계는 다음을 의미한다.
Given-When-Then = 준비 - 실행 - 검증 이다.
- Given(준비): 어떠한 데이터가 준비 되었을때
- When(실행): 어떠한 함수를 실행하면
- Then(검증): 어떠한 결과가 나와야 한다.
심플하지만, 테스트 코드를 작성시 준비/실행/검증의 세 부분으로 나누기만 하면된다.
추가적으로 어떤 메소드가 몇번 호출되었는지 확인하기 위한 verift단계도 사용하는 경우가 있는데, 실용성이 크지는 않으므로 메소드의 호출 횟수가 중요한 테스트 에서만 사용한다.
Simple 구조
@DisplayName("Given When Then 테스트")
@Test
void ginvenWhenThenTest() {
// given
// when
// then
}
2. 테스트 예제
복리 계산 코드
예를 들어 아래와 같이 원금과 이자를 입력했을때 1년뒤 얼마를 받을수 있는지 계산해주는 코드가 있다
/**
* 이자 계산기
*/
public class InterestCalculator {
private double payment;
private double interest;
private int term;
public InterestCalculator(double payment, double interest) {
this.payment = payment;
this.interest = interest;
this.term = 12;
}
public InterestCalculator(double payment, double interest, int term) {
this.payment = payment;
this.interest = interest;
this.term = term;
}
public double calculateCompoundInterest() {
if (!isValid()) {
throw new RuntimeException("올바른 값이 아닙니다.");
}
// 월납입금*{(1+r)((n+1)/12)-(1+r)(1/12)}/{(1+r)(1/12)-1}
return payment * ((1 + interest) * ((term + 1) / 12) - (1+interest)*(1/12)) / (1+interest)*(1/12) -1;
}
private boolean isValid() {
if (!isPrincipalValid()) {
throw new RuntimeException("올바른 금액이 아닙니다.");
}
if (!isInterestValid()) {
throw new RuntimeException("올바른 값이 아닙니다.");
}
return true;
}
private boolean isPrincipalValid() {
return this.payment > 0;
}
private boolean isInterestValid() {
return interest > 0;
}
}
위와 같은 이자 계산기에 대한 테스트 코드들을 작성해보자
우선 이자를 계산하기 위해선 계산기에 최소 원금과 이자를 입력해야 한다. 그렇기에 given 단계에서 이 값들을 생성해주도록 하자.
@Test
@DisplayName("이자 default 테스트")
void 이자_테스트() {
// given
final InterestCalculator interestCalculator = new InterestCalculator(1000, 12);
// when
// then
}
준비가 끝났다면 주어진 값들을 통해 계산을 해야한다. 이에 대한 when 코드를 작성한다.
@Test
@DisplayName("이자 default 테스트")
void 이자_테스트() {
// given
final InterestCalculator interestCalculator = new InterestCalculator(1000, 0.1);
// when
final double money = interestCalculator.calculateCompoundInterest();
// then
}
이제 최종적으로 우리가 받은 최종금액이 payment * term 보다 많은 금액을 돌려주었는지 확인해 보면 좋을것 같다. (좀 에매하다,, 테스트 검증이)
@Test
@DisplayName("이자 default 테스트")
void 이자_테스트() {
// given
double payment = 10000;
double interest = 0.1;
int term = 12;
final InterestCalculator interestCalculator = new InterestCalculator(payment, interest, term);
// when
final double money = interestCalculator.calculateCompoundInterest();
// then
assertEquals(money > payment*term, true);
}
then의 검증이 조금 어색하긴 하지만, 이렇게 사용하면 된다. 위와 같이 간단한 자바 어플리케이션은 어떤 메소드가 다른 객체와 메세지를 주고 받을 필요가 없기 떄문에 단위 테스트 작성이 간단하다. 하지만 일반적인 어플리케이션은 위의 코드보다 상당히 복잡하고, 여러 객체들이 메세지를 주고 받기떄문에 Spring과 같은 웹 어플리케이션에서 어떻게 단위 테스트를 작성하는지에 대해서는 뒤에서 좀더 살펴보도록 한다.