2016-05-25 7 views
0

私は仕事中に面白いケースを見つけました。あなたが私を助けてくれることを願っています。入れ子になった豆を注入する

テスト中に特定のメソッド動作を変更するには、モックを挿入する必要があります。問題は、Bean構造体がネストされており、このBeanが他のBean内部にあり、テストメソッドからアクセスできないということです。私のコードは次のようになります:

@Component 
class TestedService { 
    @Autowired 
    NestedService nestedService; 
} 

@Component 
class NestedService { 
    @Autowired 
    MoreNestedService moreNestedService; 
} 

@Component 
class MoreNestedService { 
    @Autowired 
    NestedDao nestedDao; 
} 

@Component 
class NestedDao { 
    public int method(){ 
    //typical dao method, details omitted 
    }; 
} 

私のテストでは、私はNestedDao.methodを呼んで欲しいと思います。

class Test { 
    @Mock 
    NestedDao nestedDao; 

    @InjectMocks 
    TestedService testedSevice; 

    @Test 
    void test() { 
    Mockito.when(nestedDao.method()).thenReturn(1); 
    //data preparation omitted 
    testedSevice.callNestedServiceThatCallsNestedDaoMethod(); 
    //assertions omitted 
    } 
} 

私はinitMocks行うにしようとしている:私のテストクラス時に注釈を追加する

また
@BeforeMethod 
    public void setUp() throws Exception { 
    MockitoAnnotations.initMocks(this); 
} 

を:

@RunWith(MockitoJUnitRunner.class) 

は常に(嘲笑ない)メソッドからnullpointersまたは間違った答えを得ます。

私はそれがこのDaoを模倣することが不可能にする、このネストされた呼び出しの欠陥だと思います。 また、@ InjectMocksはsetterやコンストラクタインジェクション(私フィールドでは@Autowire)だけで動作しますが、試しても機能しませんでした。

私は何が欠けていると思いますか? ;)

+0

ネストされたサービスを嘲笑しているわけではないので、どうすればいいですか?そして、通常は、nestedDaoをモックしません。代わりに、when(nestedService.callDaoMethod())。return( "daoが返すもの")を呼び出します。 – Tom

+0

さて、ネストされたサービスを模擬し、その中に何か入れ子にして、再び同じものを模擬することができますか?インターネット上でこれを行う例はありません。私が見る別の方法は、コンストラクタを使用してオブジェクトを作成することですが、依存関係は私にとっては複雑すぎます(Im new in project)。 NestedDaoクラスが通常どおりに別のオブジェクトを返さなければならないことを伝えるだけでいいですね。この呼び出しは階層が深いので、これをネストしたすべてのサービスを模擬するのは難しいです。 –

+0

* "そしてそれに入れ子にされたものと再び同じものを模倣する" *それをする理由はない。これは_ユニットテストです。あなたは 'TestedService'をテストしていて、' NestedService'とそのネストされた依存関係の実装の詳細はテストしていません。たとえば、あなたのクラス 'MoreNestedService' ...このクラスはテストで言及する必要さえありません。あなたは 'TestedService'だけを模擬し、特定のメソッド呼び出しで何を返すべきかを模倣します。このメソッドがネストされたメソッドを "実生活で"呼び出すかもしれないということは今のところ問題ではありません。 – Tom

答えて

1

それは私にとって意味があります、あなたは間違っています なぜですか?

:あなたのテストで

@Component 
class TestedService { 

    @Autowired 
    NestedService nestedService; 

    String sayHello(String name){ 
    String result = "hello" + nestedService.toUpperCase(name) 
    } 
} 

@Component 
class NestedService { 

    @Autowired 
    MoreNestedService moreNestedService; 

    String toUpperCase(String name){ 
     String nameWithDotAtTheEnd = moreNestedService.atDot(name); 
     return nameWithDotAtTheEnd.toUpperCase(); 

    } 

} 

: あなたがいないダオで、TestedServiceとNestedServiceとの相互作用をテストしているためです、ダオの相互作用がNestedServiceに検証されるべきでは

がこれを見てテストします

class Test { 
    @Mock 
    NestedService nestedService; 

    @InjectMocks 
    TestedService testedSevice; 

    @Test 
    void test() { 
    Mockito.when(nestedService.toUpperCase("rene")).thenReturn("RENE."); 
    //data preparation omitted 
    Assert.assertEquals("hello RENE.", testedSevice.sayHello("rene")); 
    //assertions omitted 
    } 
} 

あなたが見るように、TestedServiceの依存関係がうまくいれば、文字列の接頭辞としてhelloが追加されていることを確認する必要があります。

1

@Mockと@InjectionMockの代わりに@MockBeanを使用できます。

@RunWith(SpringRunner.class) 
@SpringBootTest 
class Test { 
    @MockBean 
    NestedDao nestedDao; 

    @Autowired 
    TestedService testedSevice; 

    @Test 
    void test() { 
    Mockito.when(nestedDao.method()).thenReturn(1); 
    //data preparation omitted 
    testedSevice.callNestedServiceThatCallsNestedDaoMethod(); 
    //assertions omitted 
    } 
} 
+0

「単体テスト」でさらに別のビーンを含めるという目的を疑問に思うかもしれませんが、それが適用可能かもしれない状況があります。正しいと私は言うだろう。 –

関連する問題