Mockito,验证函数被调用0次

use*_*225 7 java unit-testing mockito

我正在使用Mockito来编写我的测试用例.我有一个简单的类,其中包含一个countPerson(boolean)我有兴趣测试的函数:

public class School {
    //School is a singleton class.

    public void countPerson(boolean includeTeacher) {
        if (includeTeacher) {
            countIncludeTeacher();
            return;
        }
        countOnlyStudents();
    }

    public void countIncludeTeacher() {...}
    public void countOnlyStudents() {...}
}
Run Code Online (Sandbox Code Playgroud)

在我的单元测试中,我想测试countPerson(boolean)方法:

@Test 
public void testCountPerson() {    
    School mSchool = School.getInstance();
    School spySchool = Mockito.spy(mSchool);
    spySchool.countPerson(true);

    //Verify the function countIncludeTeacher is invoked once
    verify(spySchool).countIncludeTeacher();
    //Until here things are working well.

    spySchool.countPerson(false);
    //ERROR HERE when I try to verify the function has 0 times invoke
    verify(spySchool, times(0)).countIncludeTeacher();      
}
Run Code Online (Sandbox Code Playgroud)

我有以下错误:

org.mockito.exceptions.verification.NeverWantedButInvoked:school.countIncludeTeacher(); 从未想过这里:(SchoolTest.java 20)

为什么0次验证不起作用?

Tun*_*aki 8

实际上,问题是每次verify调用都是在同一个spySchool实例上进行的.让我解释:

@Test 
public void testCountPerson() {    
    School mSchool = School.getInstance();
    School spySchool = Mockito.spy(mSchool); // a spy is created here, Mockito is listening in.
    spySchool.countPerson(true); // real method is invoked
    verify(spySchool).countIncludeTeacher(); // our spy identified that countIncludeTeacher was called

    spySchool.countPerson(false); // real method is invoked
    verify(spySchool, times(0)).countIncludeTeacher(); // our spy still identified that countIncludeTeacher was called, before it was called before
}
Run Code Online (Sandbox Code Playgroud)

事情是,在最新的情况下verify,它失败了,因为countIncludeTeacher之前调用了间谍方法并且调用未被注销.

您可以使用verifyNoMoreInteractions它来验证对象没有更多的交互.您也可以重置该对象.

但请注意,这不是真的不推荐,引用Mockito Javadoc:

一句警告:谁做了很多经典的一些用户,期望-运行-验证嘲讽倾向于使用verifyNoMoreInteractions()非常频繁,甚至在每个测试方法.verifyNoMoreInteractions()不建议在每种测试方法中使用.verifyNoMoreInteractions()是交互测试工具包中的一个方便的断言.仅在相关时使用它.滥用它会导致过度指定,不易维护的测试.你可以在这里找到进一步阅读.

Smart Mockito用户几乎不使用此功能,因为他们知道这可能是测试不佳的标志.通常,您不需要重置模拟,只需为每个测试方法创建新的模拟.

而不是reset()考虑在冗长,过度指定的测试上编写简单,小巧且集中的测试方法.第一个潜在的代码气味是reset()在测试方法的中间.这可能意味着你的测试太多了.按照你的测试方法的低语:"请保持我们小,专注于单一行为".

我肯定会建议你将这个测试分成两部分:一部用于true案例,一部分用于false案例.

  • Mockito还有`never()`作为验证模式. (3认同)