2011-09-09 50 views
0

對於我的單元測試,我想使用mock來測試某個bean的自動裝載依賴項。創建模擬和注入的單元測試類正常,但將其注入豆測試失敗,將模擬注入bean失敗

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No matching bean of type [Service] 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)} 

這是我用來testContext.xml

<bean id="Service" class="org.easymock.EasyMock" factory-method="createMock"> 
    <constructor-arg value="Service" ></constructor-arg> 
</bean> 

<bean id="Controller" class="Controller"> 
    <property name="Service" ref="Service"></property> 
</bean> 

這其中的一部分豆測試(Controller.java)在佈線就失敗

@Autowired 
private Service service; 

但如果我自動裝配相同的模擬到我的單元測試類(ControllerTest.java),沒有出現錯誤,

@Autowired 
private Service service; 

注入的對象類型的

($Proxy18) EasyMock for interface Service 

任何建議,爲什麼注入豆測試是不可能的,但注入到測試工作?

親切的問候 多米尼克

回答

2

我認爲這個問題可能與事物的順序做。在ControllerTest中,我猜你正在擴展AbstractJUnit4SpringContextTests或類似的東西,它會先連接所有的bean(甚至在你有機會創建你的模擬器之前)。很難說沒有看到你的整個類(或至少是類聲明,setUp,tearDown和特定的測試方法)。

單元測試(而不是集成測試)的通常情況是不使用spring來連接任何東西 - 只需使用屬性設置器手動注入模擬協作者即可。集成測試通常不使用嘲笑 - 他們使用真實的對象。

有時候,你想做集成測試,但是你想嘲笑一個特定的合作者,因爲真正的合作者會做一些破壞性的事情或者發送一條短信或者其他東西。我在這些情況下所做的就是讓Spring按照自己想要的方式連接所有內容,然後在全部初始化完成後,使用類中的屬性設置器手動注入模擬。除非你想模擬的真實類在初始化中做了一些你真正不想要的東西,否則沒有問題。

+0

感謝您的提示!我不認爲在春天使用mock是不尋常的。在單元和集成測試中嘲笑應用程序的某些層的原因很多。但是你是對的,我們應該注意我們是否需要單元測試或集成測試。 – Dominik

+0

我不認爲在Spring應用程序中使用mocks是不尋常的。我只是認爲實際使用Spring進行模擬注入是很不尋常的,因爲Spring通常也會處理bean實例化,這正是嘲弄的核心。但是我從我的回答中放棄了這個評論,坦率地說,僅僅因爲我沒有看到它,我怎麼知道這是不尋常的?這樣做似乎很難。 – jhericks

+1

即使非常感謝您的建議。那一天我經常談論這件事,爲什麼它會出現異常。最終,我從所有Spring上下文鏈接中解除了單元測試的負擔。現在它甚至不是從AbstractJUnit4SpringContextTests派生出來的......它很漂亮,透明性和可理解性進入了測試架構:控制器是用它自己的構造函數創建的,並且-mocked-dependencies是通過ReflectionTestUtil設置的(由於缺少@Autowired字段的setter)......並且那很好,謝謝! – Dominik

1

可能這與一個隨機效果有關:Spring的bean實例化順序。

看看您的應用程序上下文配置片段,spring無法知道它必須首先創建Service類型的模擬對象,因爲它不知道具有id Service的bean的實例化將導致類型Service。如果首先創建Controller bean,這可能會阻止自動裝配。

爲了證實這一點,嘗試

<bean id="Controller" class="Controller" depends-on="Service"> 

(編輯:您可以使用自動裝配,而在明確產權的XML配置的服務,如果你刪除Controller.Service的@Autowired會發生什麼?)

在附註中提到@jhericks,我們有時在集成測試中注入模擬對象(在極少數情況下,這是絕對必要的):應用程序有一個可選參數(命令行,配置文件等) )我們可以在其中提供一個額外的xml應用程序上下文配置文檔。這個簡短的文檔覆蓋了有問題的bean的bean聲明,用模擬變體替換它。