2012-04-10 109 views
3

我正在嘗試在我的集成測試中使用嘲笑,並沒有太多的運氣。我使用Spring 3.1.1和1.9.0的Mockito,而且情況如下:NoSuchBeanDefinitionException嘲笑豆的依賴關係

@Component 
public class ClassToTest { 

    @Resource 
    private Dependency dependency; 

} 

@Component 
public class Dependency { 

    @Resource 
    private NestedDependency nestedDependency; 

} 

現在,我想要做的使用Spring的JavaConfig ClassToTest的集成測試。這是我所嘗試的,它不起作用:

@Test 
@ContextConfiguration 
public class ClassToTestIntegrationTest { 

    @Resource 
    private ClassToTest classToTest; 

    @Resource 
    private Dependency mockDependency; 

    @Test 
    public void someTest() { 
     verify(mockDependency).doStuff(); 

     // other Mockito magic... 

    } 


    @Configuration 
    static class Config { 

     @Bean 
     public ClassToTest classToTest() { 
      return new ClassToTest(); 
     } 

     @Bean 
     public Dependency dependency() { 
      return Mockito.mock(Dependency.class); 
     } 

    } 
} 

我簡化了我的設置,使問題更容易理解。實際上我有更多的依賴關係,只想嘲笑其中的一些 - 其他的都是真實的,基於從我的prod @Configuration類導入的配置。

結果發生了什麼是我得到一個NoSuchBeanDefinitionException異常,說應用程序上下文中沒有類型爲NestedDependency的bean。我不明白這一點 - 我認爲Spring會收到Mockito嘲弄的Dependency實例,甚至沒有看到它的自動裝配。由於這不起作用,我最終不得不嘲笑我的整個對象圖 - 這完全破壞了嘲弄的地步!

在此先感謝您的幫助!

回答

2

Mockito在嘲笑課程時做了些什麼,它使用創建了一個子類,如Dependency$EnhancerByMockito(IIRC)。正如你可能知道,子類繼承父字段:

@Component 
public class Dependency { 

    @Resource 
    private NestedDependency nestedDependency; 

} 


public class Dependency$EnhancerByMockito extends Dependency{ 
    //... 
} 

這意味着當模擬呈現春天還認爲,在基類中的字段。你可以做什麼:

  1. 使用的界面,這將導致的Mockito採用動態代理,而不是CGLIB生成的類

  2. 模擬NestedDependency - 我知道這只是級聯進一步

  3. 問題一個級別
  4. 用於測試

+0

待辦事項的Mockito的CGLIB子類也繼承私有字段? – 2012-04-11 08:57:12

+0

@TomMcIntyre:實際上它與Mockito/CGLIB無關。如果你創建'SubDependency extends Dependency'普通類,Spring(通過反射)仍然會找到在基類中聲明的私有字段。 CGLIB生成的類也不例外。 – 2012-04-11 09:00:42

+0

@Tomasz你不應該使用_inherit_這個詞,因爲它可能會被誤解。字段和方法保留在它們的聲明類中,並且如果它們的可見性修飾符允許它們,則可以在編譯時訪問它們。在運行時,可以通過反射訪問當前課程或父母中的這些成員。 – Brice 2012-04-11 09:38:59

4

禁用@Resource註釋掃描我的S ame問題,我找到了另一個解決方案。 當Spring實例化所有的bean時,它會檢查它是否是Mockito Mock,在這種情況下,我返回false爲注入屬性。要使用它,只是把它注射在下面

守則Spring上下文:

public class MockBeanFactory extends InstantiationAwareBeanPostProcessorAdapter { 

    private static final MockUtil mockUtil = new MockUtil(); 

    public MockBeanFactory() { 
     super(); 
    } 

    @Override 
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { 
     return !mockUtil.isMock(bean); 
    } 

} 
+0

真棒,這節省了我很多心痛!對於任何想知道如何注入的人來說,在你的Spring應用程序上下文XML中添加一行: 2013-08-21 01:24:55

+0

這個解決了我的問題,謝謝你! – dwjohnston 2015-08-04 00:00:28