728x90
[TDD] Test Double
테스트를 위해 실제 구현을 대체하는 대역 객체를 통칭합니다.
종류 | 설명 |
Dummy | 파라미터 전달용, 실제 동작 없음 |
Fake | 간단한 실제 동작(예: 인메모리 DB) |
Stub | 미리 정의된 응답만 제공 |
Spy | Stub 기능 + 호출 기록 기능 |
Mock | 기대 행위 설정 및 호출 검증 |
1. 예시 코드
1-1. Dummy
// Dummy 구현: 실제로는 아무런 동작도 수행하지 않음
public class DummyPaymentGateway implements PaymentGateway {
@Override
public void pay(int amount) {
// no-op
}
}
class OrderServiceTest {
@Test
void placeOrder_withDummy_shouldReturnTrue() {
PaymentGateway dummy = new DummyPaymentGateway();
OrderService service = new OrderService(dummy);
assertTrue(service.placeOrder(100)); // Gateway 동작 여부 상관없이 통과
}
}
1-2. Fake
// In-memory Fake: Map 기반 간단 구현
public class InMemoryUserRepository implements UserRepository {
private final Map<String, User> store = new HashMap<>();
@Override
public void save(User user) {
store.put(user.getId(), user);
}
@Override
public Optional<User> findById(String id) {
return Optional.ofNullable(store.get(id));
}
}
class UserServiceTest {
@Test
void findUser_withFakeRepo_shouldReturnUser() {
UserRepository fakeRepo = new InMemoryUserRepository();
User alice = new User("1", "Alice");
fakeRepo.save(alice);
Optional<User> found = fakeRepo.findById("1");
assertTrue(found.isPresent());
assertEquals("Alice", found.get().getName());
}
}
1-3. Stub
// Stub: 고정 환율 리턴
public class StubExchangeRateService implements ExchangeRateService {
@Override
public double getRate(String from, String to) {
return 1_200.0;
}
}
// 테스트는 위의 상태 기반 검증 예시 참고
1-4. Spy
// Spy 구현: 호출 기록 저장
public class SpyEmailService implements EmailService {
private final List<String> calls = new ArrayList<>();
@Override
public void send(String to, String body) {
calls.add(to + ":" + body);
}
public List<String> getCalls() {
return calls;
}
}
class NotificationManagerTest {
@Test
void notifyUser_withSpy_shouldRecordCall() {
SpyEmailService spy = new SpyEmailService();
NotificationManager mgr = new NotificationManager(spy);
mgr.notifyUser("user@example.com");
assertEquals(1, spy.getCalls().size());
assertEquals("user@example.com:Welcome!", spy.getCalls().get(0));
}
}
1-5. Mock
import static org.mockito.Mockito.*;
class PaymentServiceTest {
@Test
void processPayment_withMock_shouldInvokeOnce() {
// Mockito Mock
PaymentGateway mockGateway = mock(PaymentGateway.class);
OrderService service = new OrderService(mockGateway);
service.placeOrder(50);
// 기대 행위 검증
verify(mockGateway, times(1)).pay(50);
}
}
728x90
'Backend > Spring' 카테고리의 다른 글
[Spring] Transaction - @TransactionalEventListener를 이용한 이벤트 처리 (3) | 2025.08.17 |
---|---|
[Spring] Transaction - 트랜잭션 전파(Transaction Propagation) (3) | 2025.08.17 |
[Spring] @Value와 @ConfigurationProperties (0) | 2023.07.09 |
[Spring] Bean Validation과 Custom Validation (0) | 2023.07.08 |
[Spring] HTTP 요청 데이터 바인딩(@RequestParam, @ModelAttribute, @RequestBody, @RequestHeader) (0) | 2023.07.02 |