2012-04-10 9 views
3

私は統合テストでモックを使用しようとしていますが、大したことはありません。私は春の3.1.1とMockito 1.9.0を使用していて、次のような状況は次のとおりです。NoSuchBeanDefinitionException擬似Beanの依存関係について

@Component 
public class ClassToTest { 

    @Resource 
    private Dependency dependency; 

} 

@Component 
public class Dependency { 

    @Resource 
    private NestedDependency nestedDependency; 

} 

さて、私は春の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クラスからインポートされた設定に基づいて実際のものです。

何が起きるかは、アプリケーションコンテキストにNestedDependency型のBeanが存在しないことを示すNoSuchBeanDefinitionExceptionを取得することです。私はこれを理解していない - 私は、春はMockitoの模倣されたDependencyのインスタンスを受け取り、それをオートワイヤリングすることさえ見ないと思った。これが機能していないので、私はオブジェクト・グラフ全体をモックする必要があります。これは嘲笑の点を完全に打ち消します!任意の助けを事前に

ありがとう!

答えて

2

クラスをモックするときにMockitoが行うのは、Dependency$EnhancerByMockito(IIRC)のようなファンシーな名前を持つを使用してサブクラスを作成することです。あなたはおそらく知っているように、サブクラスは親からのフィールドを継承します。

@Component 
public class Dependency { 

    @Resource 
    private NestedDependency nestedDependency; 

} 


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

これはモックを提示するときの春はまだ、基本クラスのフィールドを見ていることを意味します。あなたは何ができるか:動的プロキシではなくCGLIBで生成されたクラス

  • モックNestedDependency

    を採用するMockitoの原因となります

    1. 用途のインタフェースを、 - 私はそれだけで

    2. さらなる問題あるレベルをカスケード接続することがわかっています
    3. テスト

  • +0

    ドゥMockitoのCGLIBのサブクラスには専用のフィールドを継承?? –

    +0

    @TomMcIntyre:実際にはMockito/CGLIBとは関係ありません。 'SubDependency extends Dependency'普通クラスを作成した場合、Springは(リフレクションを介して)まだ基本クラスで宣言されたプライベートフィールドを見つけるでしょう。 CGLIB生成クラスも例外ではありません。 –

    +0

    @Tomasz潜在的に誤解される可能性があるので、_inherit_という単語は使用しないでください。フィールドとメソッドは宣言クラスにとどまり、可視性修飾子で許可されている場合はコンパイル時にアクセスできます。実行時に、現在のクラスまたは親のメンバーは、リフレクションによってアクセスできます。 – Brice

    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に次のような行を追加してください。

    +0

    これは私のために解決しました。 – dwjohnston

    関連する問題