【问题标题】:Mockito verify order / sequence of method callsMockito 验证方法调用的顺序/顺序
【发布时间】:2014-03-21 00:23:05
【问题描述】:

有没有办法验证在 Mockito 中 methodTwo 之前是否调用了 methodOne

public class ServiceClassA {
    public void methodOne(){}
 }

public class ServiceClassB {
    public void methodTwo(){}
 }

public class TestClass {
    public void method(){
        ServiceClassA serviceA = new ServiceClassA();
        ServiceClassB serviceB = new ServiceClassB();
        serviceA.methodOne();
        serviceB.methodTwo();
    }
}

【问题讨论】:

    标签: java unit-testing mockito


    【解决方案1】:

    InOrder 帮助您做到这一点。

    ServiceClassA firstMock = mock(ServiceClassA.class);
    ServiceClassB secondMock = mock(ServiceClassB.class);
    
    Mockito.doNothing().when(firstMock).methodOne();   
    Mockito.doNothing().when(secondMock).methodTwo();  
    
    //create inOrder object passing any mocks that need to be verified in order
    InOrder inOrder = inOrder(firstMock, secondMock);
    
    //following will make sure that firstMock was called before secondMock
    inOrder.verify(firstMock).methodOne();
    inOrder.verify(secondMock).methodTwo();
    

    【讨论】:

    • 这是正确的,尽管这里不需要调用 doNothing,除非作为其他存根的占位符。默认情况下,Mockito 将静默接受 void 方法调用。
    • 它接受它们,而对象没有依赖关系如果对象有依赖关系就会出现异常=)
    • 在本例中的最后一次验证之后考虑inOrder.verifyNoMoreInteractions();,以验证没有进行其他调用。
    • 澄清一下:在验证之前定义 inOrder 是安全的 - 在调用模拟上的一些(经过测试的)方法之后。
    • inOrder(firstMock, secondMock)inOrder(secondMock, firstMock) 的结果是否相同?也许您可以更新答案以对此进行说明。
    【解决方案2】:

    请注意,您还可以使用 InOrder 类来验证是否在单个模拟上按顺序调用各种方法,而不仅仅是在两个或多个模拟上。

    假设我有两个班级FooBar

    public class Foo {
      public void first() {}
      public void second() {}
    }
    
    public class Bar {
      public void firstThenSecond(Foo foo) {
        foo.first();
        foo.second();
      }
    }
    

    然后我可以添加一个测试类来测试BarfirstThenSecond() 方法实际上调用first(),然后是second(),而不是second(),然后是first()。见以下测试代码:

    public class BarTest {
      @Test
      public void testFirstThenSecond() {
        Bar bar = new Bar();
        Foo mockFoo = Mockito.mock(Foo.class);
        bar.firstThenSecond(mockFoo);
    
        InOrder orderVerifier = Mockito.inOrder(mockFoo);
        // These lines will PASS
        orderVerifier.verify(mockFoo).first();
        orderVerifier.verify(mockFoo).second();
    
        // These lines will FAIL
        // orderVerifier.verify(mockFoo).second();
        // orderVerifier.verify(mockFoo).first();
      }
    }
    

    【讨论】:

    • 这应该是对已接受答案的评论,而不是全新的答案。
    • 我不同意你的评论@ach 代码示例有帮助,所以一个新的答案是有意义的。
    • 有没有办法验证同一个方法被调用了两次,但是验证传入参数的顺序?例如首先是find('foo'),然后是find('bar')
    • 看起来这可能是我的答案stackoverflow.com/questions/36573399/…
    • 这实际上是一个比公认答案更好的例子,因为它显示了比doNothing()更典型的用法
    【解决方案3】:

    是的,文档中对此进行了描述。您必须使用InOrder 类。

    示例(假设已经创建了两个模拟):

    InOrder inOrder = inOrder(serviceAMock, serviceBMock);
    
    inOrder.verify(serviceAMock).methodOne();
    inOrder.verify(serviceBMock).methodTwo();
    

    【讨论】:

      【解决方案4】:

      对于 Kotlin 用户,你可以这样:

      class MyTrackerTest {
          private val trackEventUseCase: TrackEventUseCase = mock()
          private val sut = MyTracker(trackEventUseCase)
      
          @Test
          fun `trackSomething SHOULD invoke tracker use case twice with correct event names WHEN called`() {
              sut.trackSomething()
      
              trackEventUseCase.inOrder {
                  verify().invoke("Is it August?")
                  verify().invoke("No!")
              }
          }
      

      }

      【讨论】:

        【解决方案5】:

        BDD 是

        @Test
        public void testOrderWithBDD() {
        
        
            // Given
            ServiceClassA firstMock = mock(ServiceClassA.class);
            ServiceClassB secondMock = mock(ServiceClassB.class);
        
            //create inOrder object passing any mocks that need to be verified in order
            InOrder inOrder = inOrder(firstMock, secondMock);
        
            willDoNothing().given(firstMock).methodOne();
            willDoNothing().given(secondMock).methodTwo();
        
            // When
            firstMock.methodOne();
            secondMock.methodTwo();
        
            // Then
            then(firstMock).should(inOrder).methodOne();
            then(secondMock).should(inOrder).methodTwo();
        
        
        }
        

        【讨论】:

          猜你喜欢
          • 2015-12-30
          • 2023-03-22
          • 2012-09-07
          • 2018-05-15
          • 1970-01-01
          • 1970-01-01
          • 2017-08-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多