[JUnit] Spy

반응형

이번글에서는 test에서 특정 메서드만 override 하는 방법인 Spy에 대해 알아보도록 하겠습니다.

1. Mock Instance

우리는 이전 글에서 Stub와 Mock을 사용해 특정 인스턴스의 business logic을 override 하는 방법을 살펴보았습니다.

image.png

즉 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 사용법과 굉장히 비슷합니다.

image.png

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을 활용한 실용주의 단위 테스트

COUPANG

www.coupang.com

파트너스 활동을 통해 일정액의 수수료를 제공받을 수 있음


반응형

'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

댓글

Designed by JB FACTORY