정의

TestDouble은 실제 객체 대신 테스트에서 사용하는 대체 객체를 말한다.

테스트 자동화에서 여러 객체들이 의존성을 가지고 있는 경우 테스트하는데 어려움이 있다. 예를 들어 고객정보를 조회하는 API는 Database에 의존한다. 이런 경우 Database의 상태에 따라 테스트 결과가 달라질 수 있다. 반면에 의존 관계가 간단한 경우 테스트 대상에만 집중할 수 있다. TestDouble은 이런 의존관계를 줄여주는 역할을 한다.

🧩 TestDouble의 종류

TestDouble은 크게 Dummy, Fake, Stub, Spy, Mock 5가지로 나뉜다.

Dummy

Dummy는 가장 기본적인 TestDouble이다. 인스턴스화는 필요하지만 기능은 필요하지 않을 경우 사용한다. Dummy 객체의 메서드는 보통 아무런 동작을 하지 않는다.

public class PrintWarningDummy implements PrintWarning {
    @Override
    public void print() {
        // 아무 동작도 하지 않음
    }
}

Fake

Fake는 실제와 비슷한 로직을 가진 단순한 구현체다. 복잡한 로직 대신 테스트용으로 동작하는 가짜 객체를 사용한다.

public class FakeUserRepository implements UserRepository {
    private Collection<User> users = new ArrayList<>();

    @Override
    public void save(User user) {
        if (findById(user.getId()) ** null) {
            users.add(user);
        }
    }

    @Override
    public User findById(long id) {
        for (User user : users) {
            if (user.getId() ** id) {
                return user;
            }
        }
        return null;
    }
}

Stub

Stub는 미리 정해진 결과만 반환하는 객체다. 외부 호출 없이 단순히 값을 돌려주기 위해 사용한다.

public class StubUserRepository implements UserRepository {
    @Override
    public User findById(long id) {
        return new User(id, "Test User");
    }
}

Spy

Spy는 호출 여부나 횟수 같은 정보를 기록하는 객체다.

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;
    }
}

Mock

Mock은 호출 기대값을 명세하고, 동작 여부를 검증하는 객체다.
주로 행위 검증에 사용한다.

@ExtendWith(MockitoExtension.class)
public class UserServiceTest {
    @Mock
    private UserRepository userRepository;

    @Test
    void test() {
        when(userRepository.findById(anyLong())).thenReturn(new User(1, "Test User"));

        User actual = userService.findById(1);
        assertThat(actual.getId()).isEqualTo(1);
        assertThat(actual.getName()).isEqualTo("Test User");
    }
}

연결문서

댓글남기기