对于我的单元测试,我想使用模拟来测试被测bean的一些自动连接依赖项。创建模拟并将其正确注入单元测试类,但是将其注入到测试中的bean中失败
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No matching bean of type [Service] found for
dependency: expected at least 1 bean which qualifies as autowire candidate for this
dependency. Dependency annotations:
{@org.springframework.beans.factory.annotation.Autowired(required=true)}
这是我用过的testContext.xml
<bean id="Service" class="org.easymock.EasyMock" factory-method="createMock">
<constructor-arg value="Service" ></constructor-arg>
</bean>
<bean id="Controller" class="Controller">
<property name="Service" ref="Service"></property>
</bean>
这是被测bean(Controller.java)中接线失败的部分
@Autowired
private Service service;
但如果我将同一个模拟器自动装入我的单元测试类(ControllerTest.java),则不会发生错误,
@Autowired
private Service service;
注入的对象是
类型($Proxy18) EasyMock for interface Service
有任何建议为什么注入被测豆不可能,但注入测试工作?
亲切的问候 多米尼克
答案 0 :(得分:2)
我认为这个问题可能与事情的顺序有关。在ControllerTest中,我猜你正在扩展AbstractJUnit4SpringContextTests或类似的东西,首先连接你的所有bean(在你甚至有机会创建你的模拟之前)。没有看到你的全班(或者至少是类声明,setUp,tearDown和特定的测试方法),很难说。
单元测试(与集成测试相反)通常的做法是不使用spring来连接任何东西 - 只需使用属性设置器手动注入模拟协作者。集成测试通常不使用模拟 - 它们使用真实对象。
有时候,您希望进行集成测试,但是您想要模拟一个特定的协作者,因为真正的协作者会做一些具有破坏性的事情或者发送短信等等。我在这些情况下所做的就是让Spring按照自己想要的方式连接所有内容,然后在所有内容初始化之后使用类中的属性setter手动注入模拟。除非您想要模拟的真实类在初始化中做了一些您真正不想要的东西,否则没有问题。
答案 1 :(得分:1)
这可能与随机效应有关:Spring的bean实例化顺序。
查看应用程序上下文配置片段,spring无法知道它必须首先创建Service类型的模拟对象,因为它不知道具有id Service的bean的实例化将导致类型Service。如果首先创建Controller bean,这可能会阻止自动装配。
要确认这一点,请尝试
<bean id="Controller" class="Controller" depends-on="Service">
(编辑:您在服务的xml配置中使用自动装配和显式属性。如果从Controller.Service中删除@Autowired会怎样?)
在引用@jhericks的旁注中,我们有时会在集成测试中注入模拟对象(在极少数情况下这是绝对必要的)这样:应用程序有一个可选参数(命令行,配置文件左右),其中我们可以为它提供额外的xml应用程序上下文配置文档。这个简短的文档覆盖了有问题的bean的bean声明,用模拟变体替换它。