【问题标题】:Mockito: How do you verify the group order of certain groups of method calls?Mockito:您如何验证某些方法调用组的组顺序?
【发布时间】:2012-09-07 09:52:59
【问题描述】:

我正在使用 Mockito 来验证 InOrder 对象的方法调用顺序。但我对调用的总顺序不感兴趣,只是在调用其他一些方法之前发生了一组方法调用。比如这样的

@Test
public void testGroupOrder() {
    Foo foo1 = mock(Foo.class);
    Foo foo2 = mock(Foo.class);
    Bar underTest = new Bar();
    underTest.addFoo(foo1);
    underTest.addFoo(foo2);

    underTest.fire()

    InOrder inOrder = inOrder(foo1,foo2);

    inorder.verify(foo1).doThisFirst();
    inorder.verify(foo2).doThisFirst();

    inorder.verify(foo1).beforeDoingThis();
    inorder.verify(foo2).beforeDoingThis();
}

但是这个测试确实测试了太多,因为它测试了Foo 实例的顺序。但我只对不同方法的顺序感兴趣。事实上,我希望 underTest 不区分 Foo 的实例,它可能有内部顺序或没有,所以调用 foos 的顺序无关紧要。我想保留它作为实现细节。

但重要的是,doThisFirst() 已在 所有 foo 上调用,然后在 任何 其他 foo 上调用 beforeDoingThis()。可以用 Mockito 来表达吗?怎么样?

【问题讨论】:

    标签: java unit-testing tdd mockito verification


    【解决方案1】:

    Mockito 验证传递给 inorder 函数的所有模拟的顺序。因此,如果您不想验证 foos 的顺序,则需要创建两个单独的顺序。即

    @Test
    public void testGroupOrder() {
        Foo foo1 = mock(Foo.class);
        Foo foo2 = mock(Foo.class);
        Bar underTest = new Bar();
        underTest.addFoo(foo1);
        underTest.addFoo(foo2);
    
        underTest.fire()
    
        InOrder inOrderFoo1 = inOrder(foo1);
        inOrderFoo1.verify(foo1).doThisFirst();
        inOrderFoo1.verify(foo1).beforeDoingThis();
    
        InOrder inOrderFoo2 = inOrder(foo2);
        inOrderFoo2.verify(foo2).doThisFirst();
        inOrderFoo2.verify(foo2).beforeDoingThis();
    }
    

    【讨论】:

    • 如果underTest 按以下顺序调用,则您的测试通过:foo1.doThisFirst(); foo1.beforeDoingThis(); foo2.doThisFirst(); foo2.beforeDoingThis();。但这只是应该发生的事情,我想测试的是:doThisFirst() 必须在 all foos 中调用,然后在任何其他 foo 上调用 beforeDoingThis() .正确的顺序是:foo1.doThisFirst(); foo2.doThisFirst(); foo2.beforeDoingThis(); foo1.beforeDoingThis();foo2.doThisFirst(); foo1.doThisFirst(); foo2.beforeDoingThis(); foo1.beforeDoingThis(); 等等。我已编辑问题以使其更清楚。
    • 我明白你现在想做什么。我不相信这是你可以用mockito检查的东西。我认为您可能不得不回退到编写特定的模拟实现来验证这种情况。
    【解决方案2】:

    您可以通过实现自己的验证模式来访问内部(感谢this answer 教我,我的代码是基于它)。实现并不完整,但你会明白的。

    不幸的是,Mockito 没有记录这个接口,他们可能认为它是内部的(因此在未来的版本中它可能不会 100% 稳定)。

    verify(foo1, new DoFirst()).doThisFirst();
    verify(foo2, new DoFirst()).doThisFirst();
    verify(foo1, new DoSecond()).beforeDoingThis();
    verify(foo1, new DoSecond()).beforeDoingThis();
    

    然后

    // Set to true when one 
    boolean secondHasHappened = false; 
    
    // Inner classes so they can reach the boolean above.
    // Gives an error of any DoSecond verification has happened already.
    public class DoFirst implements VerificationMode {
       public void verify(VerificationData data) {
          List<Invocation> invocations = data.getAllInvocations()
          InvocationMatcher matcher = data.getWanted();
          Invocation invocation = invocations.get(invocations.size() - 1);
          if (wanted.matches(invocation) && secondHasHappened) throw new MockitoException("...");
       }
    }
    
    // Registers no more DoFirst are allowed to match.
    public class DoSecond implements VerificationMode {
        public void verify(VerificationData data) {
           List<Invocation> invocations = data.getAllInvocations()
           InvocationMatcher matcher = data.getWanted();
           Invocation invocation = invocations.get(invocations.size() - 1);
           if (!wanted.matches(invocation)) secondHasHappened = true;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2014-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-30
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多