【问题标题】:Mockito verify a function is invoked once in my case在我的情况下,Mockito 验证一个函数被调用一次
【发布时间】:2015-11-12 11:25:40
【问题描述】:

我正在使用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)函数:

public class SchoolTest{
   private School mSchool;
   @Before
   public void setUp(){
      mSchool = School.getInstance();
   }
   @Test 
   public void testCountPerson() {
       mSchool.countPerson(true);
       //How to test/verify countIncludeTeacher() is invoked once?
   }
}

如何使用 Mockito 来检查/验证 countIncludeTeacher() 在我的测试用例中被调用一次?

【问题讨论】:

  • @mayooran 在技术上不是重复的,这里的用例是不同的:OP 需要验证在同一个对象上调用了不同的方法。
  • @mayooran,它根本没有重复。请仔细查看我的代码,我不是在验证对另一个对象的方法调用。如果您投了反对票,请撤消反对票。
  • 这是因为当你模拟School 类时,即使调用mockSchool.countPerson(true); 它也没有执行那个方法,因为你在“模拟”。尝试使用Mockito.spy
  • @Valijon 没错,这就是为什么它没有重复,因为它根本没有提到间谍。

标签: java unit-testing mockito


【解决方案1】:

您必须使用spy。这里的问题是您想验证一个方法是在 real 对象上调用的,而不是在模拟对象上调用的。你不能在这里使用模拟,因为它会存根类中的所有方法,因此默认情况下也会存根 countPerson 以不执行任何操作。

@Test 
public void testCountPerson() {
    School school = School.getInstance();
    School spySchool = Mockito.spy(school);
    spySchool.countPerson(true);
    verify(spySchool).countIncludeTeacher();
}

但是,请注意,在使用间谍时应该非常小心,因为除非被存根,否则真正的方法是被调用的。引用 Mockito Javadoc:

应该小心偶尔使用真正的间谍,例如在处理遗留代码时。

【讨论】:

    【解决方案2】:

    如果您只需要一次调用,则可以使用

    verify(mSchool, times(1)).countIncludeTeacher();
    

    如果你想检查交互,而你不在乎它发生的频率,那么做

    verify(mSchool).countIncludeTeacher();
    

    【讨论】:

    • 请看我的更新,我嘲笑了学校,但出错了。
    【解决方案3】:
    verify(mSchool, times(1)).countIncludeTeacher();
    

    编辑: 正如@Tunaki 提到的那样,这是行不通的。你应该使用间谍。

    【讨论】:

    • 请看我的更新。我嘲笑学校,但出错了。
    • @user842225 这意味着永远不会调用 countIncludeTeacher 方法。
    • @newbieee 当mSchool 是一个模拟时它永远不会被调用,因为它不是真正的countPerson 被调用,而是一个默认情况下什么都不做的存根。
    • @user842225 Tunaki 是对的。你必须使用间谍而不是模拟
    • @newbieee ,我试过 spy(),还是报错,请看我的更新。
    【解决方案4】:

    你有两个选择。

    • 设置有 X 老师和 Y 学生的学校,并验证返回 X+Y 或仅返回 X。这将是我的偏好,因为嘲笑你正在测试的课程对我来说很恶心。这两种方法都应该经过很好的测试,所以任何错误都会在它们的测试中被发现。
    • 按照 Tunaki 的建议使用 Spy。

    【讨论】:

      【解决方案5】:

      你需要这样做

      Mockito.doNothing().when(mock).countIncludeTeacher();
      

      【讨论】:

      • 被 Mockito 模拟的方法什么都不做,如果它们不是 void,则返回默认值。这句话是多余的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-15
      • 1970-01-01
      • 2016-03-18
      • 1970-01-01
      • 1970-01-01
      • 2016-10-18
      相关资源
      最近更新 更多