问题描述
|
我有一个对我来说真的很奇怪的问题。我有以下设置:
接口:
package com.example;
public interface SomeDependency {
}
弹簧组件:
package com.example;
@Component
public class SomeClass {
}
带有EasyMock生成的模拟bean的春季测试配置:
<beans ....>
<context:component-scan base-package=\"com.example\"/>
<bean id=\"someInterfaceMock\" class=\"org.easymock.EasyMock\" factory-method=\"createMock\">
<constructor-arg value=\"com.example.someDependency\" />
</bean>
</beans>
和单元测试:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(\"/testconfig.xml\")
public class SomeClasstest {
@Autowired
SomeClass someClass;
@Autowired
SomeDependency someDependency;
@Test
public void testSomeClass() throws Exception {
assertNotNull(someClass);
}
@Test
public void testSomeDependency() throws Exception {
assertNotNull(someDependency);
}
}
该项目可以编译并且测试可以顺利通过,即成功完成SomeClass(一个“真实”对象)和SomeDependency(由EasyMock生成的模拟对象)的自动装配。
但是,如果我将SomeClass的实现更改为:
@Component
public class SomeClass {
@Autowired
SomeDependency someDependency;
}
两项测试均失败,因为
Caused by: org.springframework.beans.factory.NoSuchBeanDeFinitionException: No matching bean of type [com.example.someDependency] 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)}
所以我的问题是:
为什么Spring无法将依赖项自动关联到SomeClass(成功将相同的依赖项自动关联到SomeClasstest)?
如何更改SomeClasstest或testconfig.xml以使测试通过?
评论:实际上,由SomeClass表示的类是框架的一部分。因此,至少在合理时间内无法轻易更新。
依存关系:
春季:3.0.5。发布
EasyMock:3.0
编辑:
从Spring 3.2 RC1开始,通用工厂方法和模拟对象的问题已解决。
/马蒂亚斯
解决方法
在使用工厂通过自动装配创建bean时,似乎xml中定义的顺序实际上很重要。如果将
someInterfaceMock
声明放在component-scan
之上,它将起作用。
澄清原因:当Spring尝试自动装配SomeClass
时,它将搜索SomeDependency
类型的bean。在此阶段someInterfaceMock
仍然是工厂,因此Spring检查工厂方法EasyMock.createMock(...)
的签名,该方法返回<T>
,因此Spring仅找到不是必需类型的Object
。
更好的方法是使用Spring的14接口创建模拟对象。
这是应该起作用的基本实现:
public class EasyMockFactoryBean<T> implements FactoryBean<T> {
private Class<T> mockedClass;
public void setMockedClass(Class mockedClass) {
this.mockedClass = mockedClass;
}
public T getObject() throws Exception {
return EasyMock.createMock(mockedClass);
}
public Class<T> getObjectType() {
return mockedClass;
}
public boolean isSingleton() {
return true;
}
}
这是bean的定义(顺序无关紧要!):
<bean class=\"com.example.EasyMockFactoryBean\">
<property name=\"mockedClass\" value=\"com.example.Dependancy\"/>
</bean>