自动装配EasyMock工厂方法生成的咖啡豆?

问题描述

| 我有一个对我来说真的很奇怪的问题。我有以下设置: 接口:
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>