Test Double
Test Double이란?
데이터베이스로부터 조회한 값을 연산하는 비즈니스로직을 구현했다고 하면 해당 로직을 테스트하기 위해선 항상 데이터베이스의 영향을 받을 것이고, 이는 데이터베이스의 상태에 따라 다른 결과를 유발할 수 있다.
-> 객체와 연관된 객체를 사용하기가 어렵고 모호할 때 대신해 줄 수 있는 객체를 Test Double이라고 한다.
Test Double의 종류
크게 Dummy, Fake, Stub, Spy, Mock으로 나눠진다.
1. Dummy
- 가장 기본적인 테스트 더블
- 인스턴스화된 객체가 필요하지만 기능은 필요하지 않는 경우
- 객체는 전달되지만 사용되지 않는 객체
public interface AccountDao{
void showMember();
}
public class AccountDaoDummy implements AccountDao{
@Override
public void showMember{
//Dummy
}
}
AccountDaoDummy는 아무런 기능을 하지 않고 반환값도 없다. Clinet입장에서는 Dummy를 호출하기만 하면 되는 테스트이므로 내부 동작과는 상관없이 테스트 성공함
2. Fake
- 실제로 사용된 객체는 아니지만 같은 동작을 하는 구현된 객체
- 객체의 단순화된 버전
- 동작의 구현은 되어있지만 프로덕션에서 사용할 수 는 없는 객체
LoginService를 테스트하기 위해서는 AccountDao가 필요하다. 하지만 아직 구현되지 않았거나 독립적으로 미리 테스트하고 싶다면 Fake객체를 사용해서 FakeAccountDao객체는 임의의 Map를 생성하여 진짜인 것처럼 Service가 보낸 메세지에 반응한다.
public class FakeAccountRepository implements AccountRepository {
Map<User, Account> accounts = new HashMap<>();
public FakeAccountRepository() {
this.accounts.put(new User("[email protected]"), new UserAccount());
this.accounts.put(new User("[email protected]"), new AdminAccount());
}
String getPasswordHash(User user) {
return accounts.get(user).getPasswordHash();
}
}
실제 데이터베이스 설계를 연기하면서 테스트를 신속하게 실행
Stub
- Dummy 데이터가 실제로 동작하도록 만들어둔 객체
- 인터페이스 또는 기본 클래스가 최소한으로 구현된 상태
- 테스트에서 호출된 요청에 대해 미리 준비해둔 결과를 제공
@Before
public void setUp() throws Exception {
gradebook = mock(Gradebook.class);
student = new Student();
}
@Test
public void calculates_grades_average_for_student() {
when(gradebook.gradesFor(student)).thenReturn(grades(8, 6, 10)); //stubbing gradebook
double averageGrades = new GradesService(gradebook).averageGrades(student);
assertThat(averageGrades).isEqualTo(8.0);
}
실제 객체 대신 Stub(when을 이용하여 반환할 데이터를 미리 정의)을 도입하고 어떤 데이터를 반환해야 하는지 정의 후 리턴
Spy
- Stub의 역할을 가지면서 호출된 내용에 대한 약간의 정보를 기록
- 자기 자신이 호출되었을 때 확인이 필요한 부분을 기록
- 실제 객체처럼 동작시킬 수도 있고, 필요한 부분에 대해서 Stub로 만들어서 동작을 지정할 수 있다.
public class MailingService {
private int sendMailCount = 0;
private Collection<Mail> mails = new ArrayList<>();
public void sendMail(Mail mail) {
sendMailCount++;
mails.add(mail);
}
public long getSendMailCount() {
return sendMailCount;
}
}
Mockito 프레임워크의 verify()메서드가 같은 역할을 한다.
Mock
- 행위를 검증하기 위해 가짜 객체를 만들고 테스트하는 방법
- Stub 상태를 검증할 때 사용
@Test
public void mockTest(){
List mockedList = mock(List.class);
// 행위 추가
mockedList.add("one");
mockedList.clear();
// 행위 검증
verify(mockedList).add("one");
verify(mockedList).clear();
}
정리
테스트를 진행한다면 위의 항목들 중에서 어떤 테스트 더블이 필요할지 결정하고, 결정한 테스트가 경계를 벗어나는지 보며 가능한 최소한의 테스트를 선택해야 한다.
순서대로 Dumny -> Stub -> Fake -> Spy -> Mock
참고
https://codinghack.tistory.com/92
https://tecoble.techcourse.co.kr/post/2020-09-19-what-is-test-double/
Author And Source
이 문제에 관하여(Test Double), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@pkjeogus/Test-Double저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)