【问题标题】:Autowiring of beans generated by EasyMock factory-method?自动装配由 EasyMock 工厂方法生成的 bean?
【发布时间】:2011-09-14 11:07:24
【问题描述】:

我有一个对我来说似乎很奇怪的问题。我有以下设置:

一个接口:

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)}

所以我的问题是:

  1. 为什么 Spring 无法将依赖项自动装配到 SomeClass(当它成功地将相同的依赖项自动装配到 SomeClassTest 时)?
  2. 如何更改 SomeClassTesttestconfig.xml 以使测试通过?

评论:实际上,SomeClass 所代表的类是框架的一部分。因此,它不能轻易更新,至少不能在合理的时间内更新。

依赖关系:

  • 春季:3.0.5.RELEASE
  • EasyMock:3.0

编辑:

从 Spring 3.2 RC1 开始,泛型工厂方法和模拟对象的问题一直是 solved

/马蒂亚斯

【问题讨论】:

    标签: java spring easymock autowired factory-method


    【解决方案1】:

    在使用工厂创建具有自动装配功能的 bean 时,xml 中定义的顺序似乎很重要。如果您将someInterfaceMock 的声明放在component-scan 上方,它将起作用。

    解释一下原因:当 Spring 尝试自动装配 SomeClass 时,它会搜索 SomeDependency 类型的 bean。在这个阶段,someInterfaceMock 仍然是一个工厂,所以 Spring 检查工厂方法 EasyMock.createMock(...) 的签名,它返回 &lt;T&gt;,所以 Spring 只找到一个不是所需类型的 Object

    更好的方法是使用 Spring 的 FactoryBean 接口来创建你的模拟。

    这是一个应该可以工作的基本实现:

    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>    
    

    【讨论】:

    • 谢谢!该命令起到了作用,但我认为我将使用 EasyMockFactoryBean 实现,考虑到我以后可能必须模拟其他依赖项。
    猜你喜欢
    • 1970-01-01
    • 2018-03-16
    • 2011-12-17
    • 1970-01-01
    • 2020-10-22
    • 2016-09-27
    • 1970-01-01
    • 1970-01-01
    • 2012-12-04
    相关资源
    最近更新 更多