[JUnit] Spy
- JUnit
- 2020. 8. 20.
이번글에서는 test에서 특정 메서드만 override 하는 방법인 Spy에 대해 알아보도록 하겠습니다.
1. Mock Instance
우리는 이전 글에서 Stub와 Mock을 사용해 특정 인스턴스의 business logic을 override 하는 방법을 살펴보았습니다.
즉 Stub와 Mock을 사용했다면 해당 인스턴스 내부의 모든 business logic의 수행은 무력화 되며, 하드코딩으로 직접 명시한 메서드가 아닐 경우에는 null을 return 할 것입니다.
예를 들어 아래와 같은 LoanApplication을 Mock으로 생성한 경우, 아래의 모든 메서드는 실행되지 않으며, 각 메서드를 test에서 사용하고자 한다면 return 값을 직접 하드코딩해 명시해줘야 했습니다.
LoanApplication
@Entity
public class LoanApplication
{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String name;
private int principal; // amount borrowed
private int termInMonths;
private BigDecimal repayment;
private Boolean approved;
public Boolean getApproved() {
return approved;
}
public void setApproved(Boolean approved) {
this.approved = approved;
}
public BigDecimal getInterestRate() {
RestTemplate restTemplate = new RestTemplate();
return restTemplate.getForObject("http://loans.virtualpairprogrammers.com/getInterestRate", BigDecimal.class);
}
public BigDecimal getRepayment() {
return repayment;
}
public void setRepayment(BigDecimal repayment) {
this.repayment = repayment;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrincipal() {
return principal;
}
public void setPrincipal(int principal) {
this.principal = principal;
}
public int getTermInMonths() {
return termInMonths;
}
public void setTermInMonths(int termInMonths) {
this.termInMonths = termInMonths;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
그런데.. 만약 위에서 특정 메서드만 무력화 시키고 싶다면 어떻게 할까요 🤨?
예를 들어 위의 LoanApplication에서 external service의 API를 호출하는 getInterestRate 메서드만 무력화 시키고 싶을 경우 어떻게 해야될까요?
이때 사용할 수 있는 것이 Spy 입니다.
2. Spy
앞서 말씀 드린것과 같이 Spy를 사용하면 손쉽게 특정 메서드만 Mock 처리 할 수 있습니다.
LoanApplication의 business logic은 설명하지 않겠습니다. Spy가 어떻게 사용될 수 있는지만 확인해보겠습니다.
Spy로 선언한 인스턴스는 아래와 같이 특정 메서드만 override 해서 사용할 수 있습니다. 이전에 보았던 Mock 사용법과 굉장히 비슷합니다.
Spy를 사용한 test1YearLoanWholePounds 테스트는 다음과 같습니다.
test1YearLoanWholePounds
@Test
public void test1YearLoanWholePounds() {
// spy declare
LoanApplication loanApplication = spy(new LoanApplication());
// use defined method
loanApplication.setPrincipal(1200);
loanApplication.setTermInMonths(12);
// use spy
doReturn(new BigDecimal(10)).when(loanApplication).getInterestRate();
// assert
assertEquals(new BigDecimal(110), loanApplication.getRepayment());
}
위의 코드를 해석해보면 먼저 아래와 같이 Spy 인스턴스를 먼저 선언합니다.
// spy declare
LoanApplication loanApplication = spy(new LoanApplication());
이후 아래와 같이 Spy로 선언한 인스턴스는, Mock과 다르게 내부 메서드를 호출해 사용하는 것을 확인할 수 있습니다. 만약 이를 Mock으로 선언했다면, 각각의 메서드에 대한 하드코딩 결과값을 미리 작성해 놓아야 합니다.
// use defined method
loanApplication.setPrincipal(1200);
loanApplication.setTermInMonths(12);
최종적으로 Spy로 선언한 인스턴스는 특정 메서드에 대한 Mock 결과값을 지정할 수 있습니다.
// use spy
doReturn(new BigDecimal(10)).when(loanApplication).getInterestRate();
정리하자면, Spy는 특정 business logic만 mocking 할 때 사용하면 되겠습니다. 😎
참고 자료 : https://www.udemy.com/course/practical-test-driven-development-for-java-programmers/
추천서적
파트너스 활동을 통해 일정액의 수수료를 제공받을 수 있음
'JUnit' 카테고리의 다른 글
[JUnit] MockMvc (0) | 2020.08.20 |
---|---|
[JUnit] Bad Test (0) | 2020.08.20 |
[JUnit] Mock & Mockito -2 (0) | 2020.08.20 |
[JUnit] Mock & Mockito -1 (0) | 2020.08.20 |
[JUnit] Stub (0) | 2020.08.20 |