Mockito,验证函数被调用 0 次



我正在使用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() {...}
}

在我的单元测试中,我想测试 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();      
}

我有以下错误:

org.mockito.exceptions.verification.NeverWantedButInvoked: 学校计数包括教师((; 这里从来不想要: (学校测试.java 20(

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

实际上,问题是每个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
}

问题是在最新的verify中,它失败了,因为之前在间谍上调用了countIncludeTeacher方法,并且该调用未取消注册。

您可以使用 verifyNoMoreInteractions 来验证对象是否不再有交互。您也可以重置对象。

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

警告:一些做了大量经典的预期运行验证模拟的用户倾向于经常使用verifyNoMoreInteractions(),即使在每种测试方法中也是如此。 不建议在每种测试方法中使用verifyNoMoreInteractions()verifyNoMoreInteractions()是交互测试工具包中的一个方便的断言。仅在相关时才使用它。滥用它会导致过度指定、更难维护的测试。您可以在此处找到进一步的阅读。

聪明的Mockito用户几乎不使用此功能,因为他们知道这可能是测试不佳的迹象。通常,您不需要重置模拟,只需为每种测试方法创建新的模拟即可。

与其reset()请考虑编写简单、小而集中的测试方法,而不是冗长、过度指定的测试。第一个潜在的代码异味reset()在测试方法的中间。这可能意味着您测试太多了。遵循你的测试方法的耳语:"请让我们保持小,专注于单一行为"。

我绝对建议你把这个测试一分为二:一个用于true情况,一个用于false情况。

失败是因为您在测试中运行spySchool.countPerson(true)时实际上确实调用了countIncludeTeacher()。这会分支到您的其他函数,重新编码为对间谍对象的调用。

在当前设置中,您必须验证它只被调用一次,或者在运行第二个测试之前重置您的间谍对象实例。

相关内容

  • 没有找到相关文章

最新更新