이유 중 하나는 테스트 가능성입니다. 이 수업이 있다고 가정 해보십시오.
interface HttpLoader {
String load(String url);
}
interface StringOutput {
void print(String txt);
}
@Component
class MyBean {
@Autowired
MyBean(HttpLoader loader, StringOutput out) {
out.print(loader.load("http://stackoverflow.com"));
}
}
이 콩을 어떻게 테스트 할 수 있습니까? 예를 들면 다음과 같습니다.
class MyBeanTest {
public void creatingMyBean_writesStackoverflowPageToOutput() {
// setup
String stackOverflowHtml = "dummy";
StringBuilder result = new StringBuilder();
// execution
new MyBean(Collections.singletonMap("https://stackoverflow.com", stackOverflowHtml)::get, result::append);
// evaluation
assertEquals(result.toString(), stackOverflowHtml);
}
}
쉬워요?
여전히 주석에 의존하여 Spring에 의존하는 동안 코드를 변경하지 않고 (주석 정의 만) 스프링에 대한 의존성을 제거 할 수 있으며 테스트 개발자는 스프링 작동 방식에 대해 아무것도 알 필요가 없습니다 (어쨌든 그는해야하지만 봄과는 별도로 코드를 검토하고 테스트 할 수 있습니다).
ApplicationContext를 사용할 때 여전히 동일한 작업을 수행 할 수 있습니다. 그러나 ApplicationContext
거대한 인터페이스 를 조롱해야합니다 . 더미 구현이 필요하거나 Mockito와 같은 조롱 프레임 워크를 사용할 수 있습니다.
@Component
class MyBean {
@Autowired
MyBean(ApplicationContext context) {
HttpLoader loader = context.getBean(HttpLoader.class);
StringOutput out = context.getBean(StringOutput.class);
out.print(loader.load("http://stackoverflow.com"));
}
}
class MyBeanTest {
public void creatingMyBean_writesStackoverflowPageToOutput() {
// setup
String stackOverflowHtml = "dummy";
StringBuilder result = new StringBuilder();
ApplicationContext context = Mockito.mock(ApplicationContext.class);
Mockito.when(context.getBean(HttpLoader.class))
.thenReturn(Collections.singletonMap("https://stackoverflow.com", stackOverflowHtml)::get);
Mockito.when(context.getBean(StringOutput.class)).thenReturn(result::append);
// execution
new MyBean(context);
// evaluation
assertEquals(result.toString(), stackOverflowHtml);
}
}
이것은 상당히 가능성이 있지만 대부분의 사람들은 첫 번째 옵션이 더 우아하고 테스트가 더 간단하다는 데 동의 할 것입니다.
실제로 문제가되는 유일한 옵션은 다음과 같습니다.
@Component
class MyBean {
@Autowired
MyBean(StringOutput out) {
out.print(new HttpLoader().load("http://stackoverflow.com"));
}
}
이를 테스트하려면 많은 노력이 필요하거나 Bean이 각 테스트에서 stackoverflow에 연결하려고 시도합니다. 네트워크 장애가 발생하거나 (혹은 초과 액세스 속도로 인해 stackoverflow의 관리자가 사용자를 차단하면) 무작위로 테스트에 실패하게됩니다.
결론적 ApplicationContext
으로 직접 사용이 자동으로 잘못되어 모든 비용을 피해야 한다고 말하고 싶지는 않습니다 . 그러나 더 나은 옵션이 있고 대부분의 경우 더 좋은 옵션을 사용하십시오.
new MyOtherClass()
있습니까? 나는 @Autowired에 대해 알고 있지만, 나는 그것을 필드에서만 사용했고 그것은new MyOtherClass()
..