我不知道如何使用模拟来检查我的方法是否每次都被调用。我真的不知道如何描述这个问题,所以我会继续并显示我的代码:
我有两个交互类:Filter
和Filtrable
(一个接口)。Filter
类能够过滤过滤器 - 它返回过滤器(因此可以在必要时应用其他过滤器)。过滤方法只是遍历每个可过滤的行并检查该行是否被过滤 - 如果是,则添加到结果可过滤。我想测试是否真的检查了每个输入行。
这是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);
}
这里的想法是制作一个 stubbed filtrable,它由三个相同的虚拟线组成。然后将它们传递给 Filter 类并检查是否isLineFiltered
每次都使用相同的 dummyLine 准确地调用了 3 次方法。
在阅读了 Martin Fowler 的Mocks Aren't Stubs之后,我明白这是完全错误的,因为我没有在Filter
任何地方测试实际系统()!
那么如何验证“被测系统”中的方法是否使用模拟调用了 3 次呢?这是至关重要的,因为我正在尝试学习这种方法。我可以轻松地创建一个继承自 Filter 的测试类并计算isLineFiltered
调用的次数,然后检查它。我只是觉得这可以用模拟很好地完成。
我在这里使用 Mockito,如果有任何建议也可以使用它会很好(但任何其他 java 模拟框架当然会这样做)。
附言
在我运行测试后,抛出了 MockitoWanted 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,这就是为什么最终解决方案与我最初的尝试略有不同的原因。
谢谢你的帮助!