2013-02-19 90 views
0

我不知道如何使用mocks来检查我的方法是否每次都应该调用。我真的不知道如何描述这个问题,所以我会继续,只是显示我的代码:使用mocks检查每个对象在迭代期间是否被分析过

我有两个相互作用的类:FilterFiltrable(一个接口)。 Filter类可以过滤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); 
} 

当时的想法是做一个存根可滤,其中包括三个相同的虚拟线。然后将它们传递给Filter类并检查方法isLineFiltered是否每次都使用相同的dummyLine调用三次。

阅读后由马丁福勒Mocks Aren't Stubs我明白这是完全错误的,因为我不测试实际系统(Filter)在任何地方!

那么如何验证“System under Test”中的方法是否使用mock调用了三次?这是至关重要的,因为我正在尝试学习这种方法。我可以轻松地创建一个从Filter继承的测试类,并计算调用isLineFiltered的次数,然后检查它。我只是觉得这可以通过模拟很好地完成。

我在这里使用Mockito,如果有任何建议也会使用它(但任何其他的Java嘲笑框架当然会这样做)会很好。

P.S.

我运行测试后,引发了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; 
} 

SOLUTION:

以下是我已经最终完成它:

@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,所以这就是为什么最终解决方案与我最初的尝试有点不同。

感谢您的帮助!

+0

您是否也可以包含接口定义? – Jazzepi 2013-02-19 21:41:22

回答

0

你测试的问题之一是你实际上没有测试你的过滤器类,因为你也嘲笑它。

错误也是可以预料的。 您指定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); 
     } 
    } 

我没有做到这一点从我的头顶,所以它可能包含一些小失误。

+0

感谢您的输入。是否真的需要使用Autowired,Controller和RequestMapping注释?我不知道他们,我发现他们来自Spring MVC?从未使用它。基本上你已经做了一次重构,将我的isLineFiltered(你的getInfo)方法移动到另一个类中 - 这真的有必要吗?在我的用例中,两种方法都应该在过滤器类中,在我看来,没有更好的地方。 – kajman 2013-02-20 08:33:33

+0

不需要使用这些注释,也不需要移动isLineFiltered代码。以上只是如何使用mock进行测试并与您的代码无关的简单示例。你需要注意的是,我制作了一个我的控制器的实际实例(在你的情况下是过滤器类),并且我把模拟器放在那里。 – 2013-02-20 10:43:00

+0

但既然我的方法(过滤器和isLineFiltered)属于过滤器类 - 我可以使用真正的过滤器类实例验证?恐怕这是不可能的,或者我错了吗?在你的代码中,你在模拟实例上进行验证,因为两个方法都属于它,所以我必须在实例上进行验证。 – kajman 2013-02-20 12:09:38

相关问题