java EasyMock 工厂方法生成的 bean 的自动装配?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6340007/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 15:28:16  来源:igfitidea点击:

Autowiring of beans generated by EasyMock factory-method?

javaspringeasymockautowiredfactory-method

提问by matsev

I have a problem that seems really strange to me. I have the following setup:

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

An interface:

一个接口:

package com.example;

public interface SomeDependency {
}

A spring component:

一个弹簧组件:

package com.example;

@Component
public class SomeClass {
}

A spring test config with a mocked bean generated by EasyMock:

带有 EasyMock 生成的模拟 bean 的 spring 测试配置:

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

And a unit test:

还有一个单元测试:

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

The project compiles and the tests pass without any problem, i.e. autowiring of both SomeClass(a "real" object) and SomeDependency(a mock object generated by EasyMock) succeed.

项目编译通过,测试没有任何问题,即SomeClass(“真实”对象)和SomeDependency(EasyMock 生成的模拟对象)的自动装配成功。

However, if I change the implementation of SomeClassto:

但是,如果我将SomeClass的实现更改为:

@Component
public class SomeClass {

    @Autowired
    SomeDependency someDependency;
}

both tests fail because

两个测试都失败了,因为

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

So my questions are:

所以我的问题是:

  1. Why does Spring fail to autowire the dependency to SomeClass(when it succeeds autowiring the same dependency to SomeClassTest)?
  2. How can I change the SomeClassTestor testconfig.xmlto make the tests pass?
  1. 为什么春节不自动装配依赖于SomeClass的(当它成功自动装配同样依赖于SomeClassTest)?
  2. 如何更改SomeClassTesttestconfig.xml以使测试通过?

Comment: In reality the class represented by SomeClassis part of a framework. Consequently, it cannot easily be updated, at least not within reasonable time.

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

Dependencies:

依赖项:

  • Spring: 3.0.5.RELEASE
  • EasyMock: 3.0
  • 春天:3.0.5.RELEASE
  • EasyMock:3.0

Edit:

编辑:

As of Spring 3.2 RC1, the problem with generic factory methods and mock objects has been solved.

从 Spring 3.2 RC1 开始,泛型工厂方法和模拟对象的问题已经解决

/Mattias

/马蒂亚斯

回答by Wilhelm Kleu

It seems the order of the definitions in the xml actually matter when using factories to create beans with autowiring. If you place the declaration of someInterfaceMockabove component-scanit will work.

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

Some clarification why: When Spring tries to autowire SomeClassit searches for a bean of type SomeDependency. At this stage someInterfaceMockis still a factory so Spring checks the signature of the factory method EasyMock.createMock(...)which returns <T>so Spring only finds an Objectwhich isn't the type required.

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

A better way would be to use Spring's FactoryBeaninterface to create your mocks.

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

Here is a basic implementation that should work:

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

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

}

Here is the bean definition (the order won't matter!):

这是 bean 定义(顺序无关紧要!):

<bean class="com.example.EasyMockFactoryBean">
    <property name="mockedClass" value="com.example.Dependancy"/>
</bean>