테스트에서 대역은 중요한 역할을 맡아준다.
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 |
댓글