我有一个Spring 3.1 / Java / Tomcat应用程序。我有一个服务类如下:
public class SomeServiceImpl implements SomeService {
@Autowired
public AnotherService anotherService;
// other code...
这使用另一个自动装配的服务类AnotherService。这两个服务类都在serviceContext.xml文件中声明。
我正在编写junit来测试SomeServiceImpl并使用autowired来注入测试类(SomeService)以及被测试类(AnotherService)所需的mock(EasyMock)依赖项。 AnotherService的easymock依赖项在testContext.xml中定义,如下所示:
<bean id="mockAnotherService" class="org.easymock.EasyMock" factory-method="createMock" primary="true">
<constructor-arg value="com.xyz.AnotherService" />
</bean>
在我的测试类中,我配置为使用上下文文件。但是,我看到ServiceImpl正确地连接到实际的实现(这是期望的)但是,而不是AnotherService的模拟版本,concreate版本(AnotherServiceImpl)正在连接。
如何让我的依赖项的模拟版本变为有线?我不能在实际实现中使用@Resource或@Qualifier,因为这会破坏目的。我可以在我的测试课中使用它们。
答案 0 :(得分:2)
如果它们都在serviceContext.xml
中声明,并且您想要模拟其中一个,则该文件无法用于测试。拆分它以便您可以使用其中一个“真正的”Spring上下文文件与包含模拟的测试上下文相结合,或者只是手动创建bean并使用setter方法设置AnotherService
。控制反转的一个优点是允许您手动创建bean并以这种方式注入依赖项。
答案 1 :(得分:1)
您可以将serviceContext.xml导入testContext.xml,然后仅在测试用例中引用textContext.xml,而不是配置为同时使用上下文文件。
将配置文件导入另一个文件时,另一个文件有机会覆盖导入文件中的bean定义。
确保模拟的id与您的类相同 - 否则它将创建两个不同的bean。另一个问题是模拟对象没有公布正确的接口类型 - 因此按类型自动装配可能会失败。要解决该问题,您需要执行以下操作。我正在使用这种方法与mockito - 也应该为简单的模拟工作。
<bean id="anotherService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<bean class="org.easymock.EasyMock" factory-method="createMock" primary="true">
<constructor-arg value="com.xyz.AnotherService" />
</bean>
</property>
<property name="proxyInterfaces">
<value>com.xyz.AnotherService</value>
</property>
</bean>
尝试的另一件事是在类中创建创建模拟对象的Java Config样式方法。如果直接在测试类中创建它不起作用,你可以使用带有@Configuration的另一个类来创建模拟,然后在testContext.xml中将其定义为bean
@Bean
AnotherService anotherService() {
return EasyMock.createMock(AnotherService.class);
}