Mockito xác minh thứ tự / trình tự các cuộc gọi phương thức


205

Có cách nào để xác minh nếu a methodOneđược gọi trước methodTwotrong Mockito không?

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

Câu trả lời:


305

InOrder giúp bạn làm điều đó.

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();

5
Điều này là chính xác, mặc dù các cuộc gọi đến doNoth không cần thiết ở đây ngoại trừ như một trình giữ chỗ cho các gốc khác. Mockito sẽ âm thầm chấp nhận các cuộc gọi phương thức void theo mặc định.
Jeff Bowman

1
Nó chấp nhận chúng trong khi đối tượng không có phụ thuộc nếu đối tượng có phụ thuộc sẽ có ngoại lệ =)
Koitoer

14
xem xét inOrder.verifyNoMoreInteractions();sau lần xác minh cuối cùng trong ví dụ này để xác minh rằng không có cuộc gọi nào khác được thực hiện.
DwB

1
Chỉ cần làm rõ: Sẽ an toàn khi xác định inOrder ngay trước khi xác minh - sau khi gọi một số phương thức (đã thử nghiệm) trên giả.
dùng3078523

Là kết quả giống nhau cho inOrder(firstMock, secondMock)inOrder(secondMock, firstMock)? Có lẽ bạn có thể cập nhật câu trả lời để ghi chú về điều này.
kevinarpe

94

Lưu ý rằng bạn cũng có thể sử dụng lớp InOrder để xác minh rằng các phương thức khác nhau được gọi theo thứ tự trên một giả, không chỉ trên hai hoặc nhiều giả.

Giả sử tôi có hai lớp FooBar:

public class Foo {
  public void first() {}
  public void second() {}
}

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

Sau đó tôi có thể thêm một lớp thử nghiệm để kiểm tra rằng Bar's firstThenSecond()phương pháp thực sự kêu gọi first(), sau đó second(), và không second(), sau đó first(). Xem mã kiểm tra sau:

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

1
Điều này nên là một nhận xét về câu trả lời được chấp nhận, không phải là một câu trả lời hoàn toàn mới.
ach

12
Tôi không đồng ý với nhận xét của bạn @ach Mẫu mã giúp, vì vậy một câu trả lời mới có ý nghĩa.
Snekse

2
Có cách nào để xác minh cùng một phương thức được gọi hai lần, nhưng xác minh thứ tự của các tham số được truyền vào? ví dụ: Đầu tiên find('foo'), sau đófind('bar')
Snekse

1
Có vẻ như đây có thể là câu trả lời của tôi stackoverflow.com/questions/36573399/iêu
Snekse

3
Đây thực sự là một ví dụ tốt hơn câu trả lời được chấp nhận vì nó cho thấy cách sử dụng điển hình hơndoNothing()
Archimedes Trajano

37

Vâng, điều này được mô tả trong tài liệu. Bạn phải sử dụng lớp InOrder .

Ví dụ (giả sử hai giả đã được tạo):

InOrder inOrder = inOrder(serviceAMock, serviceBMock);

inOrder.verify(serviceAMock).methodOne();
inOrder.verify(serviceBMock).methodTwo();

1

Với BDD, nó

@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();


}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.