테스트 작성 시 외부 요인 필요한 경우
→ 테스트 작성 및 실행, 결과 예측 어려움
ex. 자동이체 정보 등록 기능과 카드번호 검사기
AutoDebitRegister 클래스: 자동이체 등록 기능
CardNumberValidator: 카드번호 유효한지 검사 → 자동이체 정보 저장
public class AutoDebitRegister {
private CardNumberValidator validator;
private AutoDebitInfoRepository repository;
public AutoDebitRegister(CardNumberValidator validator, AutoDebitInfoRepository repository {
this.validator = validatr;
this.repository = repository;
}
public RegisterResult register(AutoDebitReq req) {
CardValidity validity = validator.validate(req.getCardNumber());
if (validity != CardValidity.VALID) {
return RegisterResult.error(validity);
}
AutoDebitInfo info = repository.findOne(req.getUserId());
if (info != null) {
info.changeCardNumber(req.getCardNumber());
} else {
AutoDebitInfo newInfo =
new AutoDebitInfo(req.getUserId(), req.getCardNumber(), LocalDateTime.now());
repository.save(newInfo);
}
return RegisterResult.success();
}
}
CardNumberValidator: 외부 API 이용 → 카드번호 유효한지 검사
public class CardNumberValidator {
public CardValidity validate(String cardNumber) {
HttpClient httpClient = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("<https://some-external-pg.com/card>"))
.header("Content-Type", "text/plain")
.POST(BodyPublishers.ofString(cardNumber))
.build();
try {
HttpResponse<String> response =
httpClient.send(request, BodyHandlers.ofString());
switch (response.body()) {
case "ok": return CardValidity.VALID;
case "bad": return CardValidity.INVALID:
case "expried": return CardValidity.EXPIRED;
case "theft": return CardValidity.THEFT;
default: return CardValidity.UNKNOWN;
}
} catch (IOException | InterruptedException e) {
return CardValidity.ERROR;
}
}
}
AutoDebitRegister 클래스 테스트
public class AutoDebitRegisterTest {
private AutoDebitRegister register;
@BeforeEach
void setUp() {
CardNumberValidator validator = new CardNumberValidator();
AutoDebitInfoRepository repository = new JpaAutoDebitInfoRepository();
register = new AutoDebitRegister(validator, repository);
}
@Test
void validCard() {
// 업체에서 받은 테스트용 유효한 카드번호 사용
AutoDebitReq req = new AutoDebitReq("user1", "1234123412341234");
RegisterResult result = this.register.register(req);
assertEquals(VALID, result.getValidity());
}
@Test
void theftCard() {
// 업체에서 받은 도난 테스트용 카드번호 사용
AutoDebitReq req = new AutoDebitReq("user1", "1234567890123456");
RegisterResult result = this.register.register(req);
assertEquals(THEFT, result.getValidity());
}
}
⇒ 테스트 대상에서 의존하는 요인 때문에 테스트 어려운 경우 대역 이용해서 테스트
CardNumberValidator 대역