Mockito:如何验证某些方法调用组的组顺序?

2022-09-03 15:24:09

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

但是这个测试确实测试得太多了,因为它测试了实例的顺序。但我只对不同方法的顺序感兴趣。事实上,我不想区分 的实例,它可能具有内部顺序,因此以何种顺序调用 foos 并不重要。我想将其保留为实现细节。FoounderTestFoo

但重要的是,之前已经调用了所有 foo,然后再调用任何其他 foo。有没有可能用Mockito来表达这一点?如何?doThisFirst()beforeDoingThis()


答案 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();
}

答案 2

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

不幸的是,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;
    }
}

推荐