


- 특정 테스트를 위해서 협력자 Object를 활용하게 된다.
- 하지만 그 중에 테스트 목적에서 벗어난 기능을 다수 포함하고 있는 협력자 or 외부 의존성이 강하게 물려있는 협력자 등을 사용하게 되면 테스트 코드를 짜기도 까다로울 뿐더러 짠다고해도 불필요한 코드나 고민이 늘어날 수밖에 없다.
- 따라서 이를 대체하기 위한 테스트용 협력자를 사용하면 좋다.
- ex) 예시
- 가령 ExRateProvider라는 인터페이스를 테스틑 하는데 있어서, 결국 구현체인 WebApiExRateProvider를 사용해야 되는데, 단순한 테스트 하나를 검증하는데도 어려움이나 복잡함이 생길 수 있다.
- 이때 ExRateProviderStub이라는 테스트용 객체를 구현하여 사용한다면 이를 대체함과 동시에, 테스트의 목적을 달성할 수 있다.
1. 구성요소를 활용한 테스트
- 테스트를 대신할 모의 객체를 만들어 테스트에 활용하면, 강한 의존성을 피할 수 있다.
class PaymentServiceTest {
@Test
void convertedAmount() throws IOException {
testAmount(BigDecimal.valueOf(500), BigDecimal.valueOf(5_000));
testAmount(BigDecimal.valueOf(1000), BigDecimal.valueOf(10_000));
testAmount(BigDecimal.valueOf(3000), BigDecimal.valueOf(30_000));
}
private static void testAmount(BigDecimal exRate, BigDecimal convertedAmount) throws IOException {
// given
PaymentService paymentService = new PaymentService(new ExRateProviderStub(exRate));
// when
Payment payment = paymentService.prepare(1L, "USD", BigDecimal.TEN);
// then
Assertions.assertThat(payment.getExRate()).isEqualByComparingTo(exRate);
Assertions.assertThat(payment.getConvertedAmount()).isEqualByComparingTo(convertedAmount);
}
}
public class ExRateProviderStub implements ExRateProvider {
private BigDecimal exRate;
public ExRateProviderStub(BigDecimal exRate) {
this.exRate = exRate;
}
public BigDecimal getExRate() {
return exRate;
}
public void setExRate(BigDecimal exRate) {
this.exRate = exRate;
}
@Override
public BigDecimal getExRate(String currency) throws IOException {
return exRate;
}
}
2. 수동 DI를 이용하는 테스트
1) 테스트용 협력자/의존 오브젝트를 테스트 대상에 직접 주입하고 테스트
- @Configuration 을 활용하여 TestObjectFactory라는 구성정보를 담은 객체를 정의한다.
- 이제 위에서 정의한 테스트용 객체를, 직접 beanFactory를 통해 가져와서 활용할 수 있다.
public class PaymentServiceSpringTest {
@Test
void convertedAmount() throws IOException {
// given
BeanFactory beanFactory = new AnnotationConfigApplicationContext(TestObjectFactory.class);
PaymentService paymentService = beanFactory.getBean(PaymentService.class);
// when
Payment payment = paymentService.prepare(1L, "USD", BigDecimal.TEN);
// then
Assertions.assertThat(payment.getExRate()).isEqualByComparingTo(BigDecimal.valueOf(1_000));
Assertions.assertThat(payment.getConvertedAmount()).isEqualByComparingTo(BigDecimal.valueOf(10_000));
}
}
@Configuration
public class TestObjectFactory {
@Bean
public PaymentService paymentService() { return new PaymentService(exRateProvider()); }
@Bean
public ExRateProvider exRateProvider() { return new ExRateProviderStub(BigDecimal.valueOf(1_000)); }
}
2) 테스트용 협력자/의존 오브젝트를 스프링의 구성 정보를 이용해서 지정하고 컨테이너로부터 테스트 대상을 가져와서 테스트
- 다음의 어노테이션 활용을 활용하여 더욱 간편하게 테스트 대상을 가져와서 테스트 할 수 있다.
- @ExtendWith
- @ContextConfiguration
- @Autowired