2011-06-14 74 views
14

我有一個似乎真的很奇怪的問題。我具有以下設置:EasyMock工廠方法生成的bean自動裝配?

的接口:

package com.example; 

public interface SomeDependency { 
} 

彈簧部件:

package com.example; 

@Component 
public class SomeClass { 
} 

彈簧測試配置與由EasyMock的產生的嘲笑豆:

<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. 爲什麼春天失敗自動裝載依賴關係到SomeClass(當它成功自動裝配相同的依賴關係時SomeClassTest)?
  2. 如何更改SomeClassTesttestconfig.xml以使測試通過?

評論:在現實中,代表SomeClass是一個框架的一部分。因此,它不能輕易更新,至少不能在合理的時間內更新。

依賴關係:

  • 春:3.0.5.RELEASE
  • 了EasyMock:3.0

編輯:

在Spring 3.2 RC1,與普通工廠的問題方法和模擬對象已被solved

/馬蒂亞斯

回答

20

它使用工廠創建具有自動裝配Bean時,似乎在XML中定義的順序實際問題。如果您將someInterfaceMock的聲明放在component-scan以上,它將起作用。

一些解釋爲什麼:當Spring試圖自動裝配SomeClass時,它將搜索一個SomeDependency類型的bean。在這個階段someInterfaceMock仍然是一家工廠,所以Spring會檢查工廠方法EasyMock.createMock(...)的簽名,它將返回<T>,所以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>  
+0

謝謝!該命令做到了這一點,但我認爲我將使用EasyMockFactoryBean實現,考慮到稍後可能需要嘲笑其他依賴關係。 – matsev 2011-06-14 07:49:44