본문으로 건너뛰기

테스트 더블 (Test Double)

테스트 더블(Test Double) 은 테스트 코드에서 실제 객체 대신 사용하는 대체 객체를 의미합니다. 실전에서 사용하는 객체를 테스트 환경에 맞게 “더블”로 바꿔치기해서 테스트를 수행할 수 있도록 도와줍니다. 이는 영화에서 배우 대신 위험한 장면을 수행하는 “스턴트 더블”에서 유래한 표현입니다.

✔️ 테스트 더블의 종류에는 무엇이 있을까? 🤔

종류목적실제 구현 여부검증 가능반환값 설정
Dummy파라미터 채우기만 목적
Fake테스트용 간단한 구현체
Stub고정된 값 반환
Spy실제 구현 + 호출 감시
Mock기대된 호출 여부 검증

더미 (Dummy)

아무런 동작도 하지 않으며, 단순히 파라미터를 채우기 위해 인스턴스화된 객체만 필요한 경우에 사용합니다.

@Test
void dummyExample() {
User dummyUser = new User("dummy"); // 실제로 사용하지 않음
NotificationService service = new NotificationService();

service.sendWelcomeEmail(dummyUser); // 내부 로직에서 user를 사용하지 않는 경우
}

스텁 (Stub)

특정 호출에 대해 미리 정해진 값을 반환하도록 설정된 객체로, 테스트에 맞게 단순히 원하는 동작을 수행합니다.

@Test
void stubExample() {
UserService userService = mock(UserService.class);
when(userService.getUserName(1L)).thenReturn("Alice"); // Stub 설정

assertEquals("Alice", userService.getUserName(1L));
}

페이크 (Fake)

실제 구현 대신, 간단하게 동작하는 객체입니다. (e.g. 메모리 DB)

class FakeUserRepository implements UserRepository {
private Map<Long, User> store = new HashMap<>();

@Override
public void save(User user) {
store.put(user.getId(), user);
}

@Override
public User findById(Long id) {
return store.get(id);
}
}

// 테스트에서 사용
@Test
void fakeExample() {
UserRepository repo = new FakeUserRepository(); // 진짜 DB 사용 안함
repo.save(new User(1L, "Alice"));
assertEquals("Alice", repo.findById(1L).getName());
}

스파이 (Spy)

스텁(Stub)의 일종으로 호출된 내역(호출 여부나 호출 횟수 등)을 기록하고, 기록한 내용은 테스트 결과를 검증할 때 주로 사용합니다.

@Test
void spyExample() {
List<String> list = spy(new ArrayList<>());

list.add("a");
list.add("b");

verify(list).add("a");
verify(list, times(2)).add(anyString());
}

목 (Mock)

행위에 대한 기대(expectation)를 설정하고 검증하는 객체로, 기대한 것처럼 동작하지 않으면 예외를 발생할 수 있습니다. 목 객체는 스텁이자 스파이기도 합니다.

@Test
void mockExample() {
EmailService mockEmailService = mock(EmailService.class);
UserService userService = new UserService(mockEmailService);

userService.registerUser("user@example.com");

verify(mockEmailService).sendWelcomeEmail("user@example.com"); // 호출 검증
}
Loading comments...