モックを使用して、メソッドが呼び出されるたびに呼び出されたかどうかを確認する方法がわかりません。この問題を説明する方法が本当にわからないので、先に進んでコードを表示します。
私には2つの相互作用するクラスがあります:Filter
とFiltrable
(インターフェース)。Filter
クラスはfiltrablesをフィルタリングできます-これはfiltrablesを返します(したがって、必要に応じて他のフィルターを適用することが可能です)。フィルタリング方法は、すべてのフィルタリング可能な行を繰り返し処理し、その行がフィルタリングされているかどうかを確認します。フィルタリングされている場合は、結果に追加します。すべての入力行が実際にチェックされていることをテストしたかったのです。
Filter
クラスのコードは次のとおりです。
public Filtrable filter(Filtrable input) {
Filtrable result = input.createEmptyFiltrable();
while(input.hasNextLine()){
Line line = input.nextLine();
if(isLineFiltered(line)){
result.addLine(line);
}
}
return result;
}
そして、これが私の(失敗した)テストの試みです:
@Test
public void testFilter(){
Filtrable mockedFiltrable = mock(Filtrable.class);
when(mockedFiltrable.createEmptyFiltrable()).thenReturn(new StringArrayFiltrable());
when(mockedFiltrable.hasNextLine()).thenReturn(true,true,true,false);
when(mockedFiltrable.nextLine()).thenReturn(dummyLine);
Filter mockedFilter = mock(Filter.class);
mockedFilter.filter(mockedFiltrable);
verify(mockedFilter, times(3)).isLineFiltered(dummyLine);
}
ここでのアイデアは、3本の同一のダミーラインで構成されるスタブフィルターを作成することでした。次に、それらをFilterクラスに渡し、メソッドisLineFiltered
が毎回同じdummyLineで正確に3回呼び出されたかどうかを確認します。
MartinFowlerによるMocksAren't Stubsを読んだ後、実際のシステム( Filter
)をどこでもテストしていないので、これは完全に間違っていることを理解しています。
では、「テスト対象システム」のメソッドがモックを使用して3回呼び出されたかどうかを確認するにはどうすればよいですか?私はこの方法論を学ぼうとしているので、これは非常に重要です。isLineFiltered
Filterを継承し、呼び出された回数をカウントしてチェックするテストクラスを簡単に作成できました。これはモックで非常にうまくできると思います。
私はここでMockitoを使用していますが、何か提案があればそれも使用するといいでしょう(ただし、他のJavaモックフレームワークでももちろん使用できます)。
PS
テストを実行した後、Mockitoからの例外Wanted but not invoked: filter.isLineFiltered
がスローされます。
編集:
フィルタリング可能なインターフェースは次のとおりです。
public interface Filtrable {
public Filtrable createEmptyFiltrable();
public boolean hasNextLine();
public void addLine(Line line);
public Line nextLine() throws FiltrableException;
}
解決:
これが私が最終的にそれをした方法です:
@Test
public void testFilter(){
Filtrable mockedFiltrable = mock(Filtrable.class);
Filtrable mockedFiltrableResult = mock(Filtrable.class);
when(mockedFiltrable.createEmptyFiltrable()).thenReturn(mockedFiltrableResult);
Iterator<Line> mockedIterator = mock(Iterator.class);
when(mockedFiltrable.iterator()).thenReturn(mockedIterator);
when(mockedIterator.hasNext()).thenReturn(true,true,true,false);
when(mockedIterator.next()).thenReturn(dummyLine);
Filter filterUnderTest = new TestFilter(true);
filterUnderTest.filter(mockedFiltrable);
verify(mockedFiltrableResult,times(3)).addLine(dummyLine);
}
FiltrableインターフェースをIterableを拡張するように変更したので、最終的な解決策は最初の試みとは少し異なります。
ご協力いただきありがとうございます!