2011-09-09 52 views
0

对于我的单元测试,我想使用mock来测试某个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> 

这其中的一部分豆测试(Controller.java)在布线就失败

@Autowired 
private Service service; 

但如果我自动装配相同的模拟到我的单元测试类(ControllerTest.java),没有出现错误,

@Autowired 
private Service service; 

注入的对象类型的

($Proxy18) EasyMock for interface Service 

任何建议,为什么注入豆测试是不可能的,但注入到测试工作?

亲切的问候 多米尼克

回答

2

我认为这个问题可能与事物的顺序做。在ControllerTest中,我猜你正在扩展AbstractJUnit4SpringContextTests或类似的东西,它会先连接所有的bean(甚至在你有机会创建你的模拟器之前)。很难说没有看到你的整个类(或至少是类声明,setUp,tearDown和特定的测试方法)。

单元测试(而不是集成测试)的通常情况是不使用spring来连接任何东西 - 只需使用属性设置器手动注入模拟协作者即可。集成测试通常不使用嘲笑 - 他们使用真实的对象。

有时候,你想做集成测试,但是你想嘲笑一个特定的合作者,因为真正的合作者会做一些破坏性的事情或者发送一条短信或者其他东西。我在这些情况下所做的就是让Spring按照自己想要的方式连接所有内容,然后在全部初始化完成后,使用类中的属性设置器手动注入模拟。除非你想模拟的真实类在初始化中做了一些你真正不想要的东西,否则没有问题。

+0

感谢您的提示!我不认为在春天使用mock是不寻常的。在单元和集成测试中嘲笑应用程序的某些层的原因很多。但是你是对的,我们应该注意我们是否需要单元测试或集成测试。 – Dominik

+0

我不认为在Spring应用程序中使用mocks是不寻常的。我只是认为实际使用Spring进行模拟注入是很不寻常的,因为Spring通常也会处理bean实例化,这正是嘲弄的核心。但是我从我的回答中放弃了这个评论,坦率地说,仅仅因为我没有看到它,我怎么知道这是不寻常的?这样做似乎很难。 – jhericks

+1

即使非常感谢您的建议。那一天我经常谈论这件事,为什么它会出现异常。最终,我从所有Spring上下文链接中解除了单元测试的负担。现在它甚至不是从AbstractJUnit4SpringContextTests派生出来的......它很漂亮,透明性和可理解性进入了测试架构:控制器是用它自己的构造函数创建的,并且-mocked-dependencies是通过ReflectionTestUtil设置的(由于缺少@Autowired字段的setter)......并且那很好,谢谢! – Dominik

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声明,用模拟变体替换它。