0

モックを使用して、メソッドが呼び出されるたびに呼び出されたかどうかを確認する方法がわかりません。この問題を説明する方法が本当にわからないので、先に進んでコードを表示します。

私には2つの相互作用するクラスがあります:FilterFiltrable(インターフェース)。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回呼び出されたかどうかを確認するにはどうすればよいですか?私はこの方法論を学ぼうとしているので、これは非常に重要です。isLineFilteredFilterを継承し、呼び出された回数をカウントしてチェックするテストクラスを簡単に作成できました。これはモックで非常にうまくできると思います。

私はここで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を拡張するように変更したので、最終的な解決策は最初の試みとは少し異なります。

ご協力いただきありがとうございます!

4

1 に答える 1

0

テストの問題の 1 つは、フィルタ クラスを実際にテストしていないことです。

エラーも予想されます。を 3 回呼び出すように指定しますがisLineFiltered、テスト対象のクラスもモックします。これにより、フィルター メソッドもモックされるため、isLineFilterメソッドは呼び出されません。

モックを使用してテストする方法の簡単な例:

@Controller
public class KajmanController {
    @Autowired
    private KajmanInfoService kajmanInfoService;

    @RequestMapping(method = RequestMethod.GET)
    public String getInfo(@RequestParam(value="myParam[]") String[] myParams){
        //some logic
        for (String param : myParams) {
            Info info = kajmanInfoService.getInfo(param);
            //some logic
        }
        //some logic
    }
}

次に、モックする必要があるのは、kajmanInfoService だけです。

したがって、テストは次のようになります。

    @RunWith(MockitoJUnitRunner.class)
    public class KajmanControllerTest {

        @Mock
        private KajmanInfoService kajmanInfoService ;

        @InjectMocks
        private KajmanController controller;

        @Test
        public void customerInfoRetrieved() {
            //some logic
            when(kajmanInfoService.getInfo(anyString()).thenReturn(expectedInfo);
            //some logic
            String[] expectedInfoArguments = {"A1","B1","C1"};
            controller.getInfo(expectedInfoArguments);
            verify(kajmanInfoService, times(3)).getInfo(anyString);
        }
    }

私は頭の上でこれを行ったので、いくつかの小さな間違いが含まれている可能性があります.

于 2013-02-19T21:42:16.500 に答える