Mockito,验证函数被调用0次

时间:2015-11-12 12:49:03

标签: 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() {...}
}

在我的单元测试中,我想测试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:       school.countIncludeTeacher();       从未想过这里:(SchoolTest.java 20)

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

2 个答案:

答案 0 :(得分:7)

实际上,问题是每个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执行此操作,该reset验证对象没有更多交互。您也可以Thread Synchronization in the .Net Framework该对象。

但请注意,实际上并不推荐这样做,引用Mockito Javadoc:

  

一句话警告:一些做过很多经典的,期望运行验证模拟的用户往往会经常使用verifyNoMoreInteractions(),即使在每种测试方法中也是如此。建议不要在每种测试方法中使用verifyNoMoreInteractions()verifyNoMoreInteractions()是交互测试工具包中的一个方便的断言。仅在相关时使用它。滥用它会导致过度指定,不易维护的测试。你可以在这里找到进一步阅读。

  

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

     

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

我肯定建议您将此测试分为两部分:一部用于true个案,一部用于false个案。

答案 1 :(得分:1)

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

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