본문 바로가기
Test

Spy

by oncerun 2022. 12. 14.
반응형

테스트에서 대역은 중요한 역할을 맡아준다.

 

Spy 객체는 기존의 함수나 메서드를 가로채고 원래의 기능을 수행하면서 특정 정보를 수집할 수 있는 기능을 제공한다.

 

예를 들어, 어떤 함수가 언제, 몇 번 호출되었는지를 기록할 수 있다. 

 

비슷하게 Mock 객체는 원래의 기능을 구현하지 않고 특정 상황에 대해 정해진 반응 수행하는 기능을 제공한다. 

 

스파이를 사용해보자

 

회원가입에 성공할 시 이메일로 회원 가입  안내 메일을 발송한다. 이를 검증하기위한 테스트 골격은 다음과 같다.

//given

//when
userRegister.register("id", "pw", "email@tistory.com");

//then

email@tistory.com으로 발송되었는지 확인

 

 

그런데 이메일 발송 여부를 어떻게 확인해야 할까? 아마 UserRegister가 EmailNotifier의 메일 발송 기능을 실행할 때 이메일 주소로 email@tistory로 보냈는지 확인하는 것이다. 

 

이럴 때 스파이 대역을 사용할 수 있다. 

이를 사용하는 코드를 만들어보자. 

 

우선 UserRegister가 의존하는 EmailNotifier 인터페이스를 만들고 이를 대신하는 SpyEmailNotifier 구현체를 만들자.

 

모든 것은 테스트 코드를 먼저 작성하고 만들었다.

 


@Test
void signUpTest() {
    //given
    UserRegister userRegister = new UserRegister(new SpyEmailNotifier());
    //when
    userRegister.register("id", "pw", "email@tistory.com");

    //then

    //email@tistory.com으로 발송되었는지 확인



}
public class SpyEmailNotifier implements EmailNotifier {

    private boolean called;
    private String email;

    public boolean isCalled() {
        return called;
    }

    public String getEmail() {
        return email;
    }
}

 

이제 스파이 대역을 이용해 메일 발송 여부를 확인하는 테스트를 실습해보자.

private EmailNotifier emailNotifier;
private UserRegister userRegister;
@BeforeEach
void beforeEach() {
    emailNotifier = new SpyEmailNotifier();
    userRegister = new UserRegister(emailNotifier);
}
@DisplayName("member signup then send e-mail")
@Test
public void whenRegisterThenSendMail() throws Exception {
    //given
    //when
    String email = "onceRun@tistory.com";
    userRegister.register("id", "pwd" , email);

    //then
    assertTrue(emailNotifier.isCalled());
    assertEquals(email, emailNotifier.getEmail());

}

 

그런데 나는 인터페이스를 아직 정의하지 않았기에 isCalled()에 문제가 있고 getEmail()이라는 메서드도 없다.

 

해당 인터페이스는 이메일 알림에 대한 역할을 하기 때문에 해당 메서드가 인터페이스에 존재해도 될 것 같다. 아니면 나중에 지우고 구현체로 바꾸면 그만이다.

 

이제 검증을 위해서는 다음 두가지를 해야 한다.

 

register() 호출 시 이메일 발송 기능을 호출한다.

스파이의 이메일 발송 기능 구현에서 호출 여부를 기록.

 

기록이 무슨 말일까? 조금 더 알아보자.

 

public void register(String id, String pw, String email) {

    emailNotifier.sendRegisterEmail(email);

}
public class SpyEmailNotifier implements EmailNotifier {

    private boolean called;
    private String email;

    public boolean isCalled() {
        return called;
    }

    public String getEmail() {
        return email;
    }

    @Override
    public void sendRegisterEmail(String email) {
        this.called = true;
    }
}

 

테스트 실행 ->

실패 -> 테스트 통과를 위해 구현.

 

@Override
public void sendRegisterEmail(String email) {
    this.called = true;
    this.email = email;
}

즉  Spy 객체는 테스트 목적으로 사용되는 객체로,

기존 객체의 메서드를 재정의하여 호출이 되었을 때 원하는 동작을 수행하도록 합니다. 이는 기존 객체의 동작을 가로채서, 테스트 코드를 작성할 때 사용되는 기능입니다.

Spy 객체는 예를 들어 기존의 메서드가 언제 호출되었는지, 어떤 인자가 전달되었는지 등을 기록하여 확인할 수 있게 해 줍니다

 

그렇지만 우리는 모의 객체를 더 많이 애용한다. 이러한 도구들이 상당히 많다. 그중 가장 많이 사용하고 애용하는 것은 아마도 Mockito일 것이다.!

 

다음에는 이러한 스텁이나 스파이를 모의 객체로 대체해보자.

 

반응형

'Test' 카테고리의 다른 글

테스트 범위와 종류  (0) 2022.12.15
테스트 가능한 설계  (2) 2022.12.15
Junit 5  (0) 2022.12.12
테스트 코드에 작성 순서가 있다고?  (0) 2022.12.10
TDD init  (0) 2022.12.10

댓글