Mockito có thể khai thác một phương thức mà không liên quan đến đối số không?


302

Tôi đang cố kiểm tra một số mã kế thừa, sử dụng Mockito.

Tôi muốn khai thác một FooDaocái được sử dụng trong sản xuất như sau:

foo = fooDao.getBar(new Bazoo());

Tôi có thể viết:

when(fooDao.getBar(new Bazoo())).thenReturn(myFoo);

Nhưng vấn đề rõ ràng getBar()là không bao giờ được gọi với cùng một Bazoođối tượng mà tôi đã sử dụng phương thức này. (Lời nguyền newnhà điều hành đó !)

Tôi sẽ thích nó nếu tôi có thể khai thác phương thức theo cách mà nó trả về myFoobất kể đối số. Không, tôi sẽ lắng nghe các đề xuất giải pháp khác, nhưng tôi thực sự muốn tránh thay đổi mã sản xuất cho đến khi có phạm vi kiểm tra hợp lý.

Câu trả lời:


456
when(
  fooDao.getBar(
    any(Bazoo.class)
  )
).thenReturn(myFoo);

hoặc (để tránh nulls):

when(
  fooDao.getBar(
    (Bazoo)notNull()
  )
).thenReturn(myFoo);

Đừng quên nhập diêm (nhiều cái khác có sẵn):

Đối với Mockito 2.1.0 trở lên:

import static org.mockito.ArgumentMatchers.*;

Đối với phiên bản cũ hơn:

import static org.mockito.Matchers.*;

2
Tôi thích nó khi câu trả lời trước khi kết thúc 'chấp nhận câu trả lời đóng băng'.
Eric Wilson

10
Có một thứ notNull(Bazoo.class)giống như any(Bazoo.class)(có lẽ nó không tồn tại vào thời điểm của câu trả lời này)
Dandre Allison

2
tôi đã có một tình huống hơi đặc biệt khi tôi có thể có một trong hai đối số có thể - Bazoohoặc Cazoocả hai đều là lớp con của, giả sử , Azoo. vì Bazootôi cần trở về foo, nhưng vì Cazootôi cần trở về bar. trong tình huống này, Matchers.any()giải pháp đề xuất không hoạt động, tuy nhiên, Matchers.isA()hoạt động hoàn hảo.
Tanvir

3
org.mockito.Matchershiện không được chấp nhận - org.mockito.ArgumentMatchersthay vào đó, hãy sử dụng import static org.mockito.ArgumentMatchers.*(xem tài liệu )
DontDivideByZero

when(myFoo.knowsWhatsUp()).thenReturn(myMoney);
6

18

Sử dụng như thế này:

when(
  fooDao.getBar(
    Matchers.<Bazoo>any()
  )
).thenReturn(myFoo);

Trước khi bạn cần nhập Mockito.Matchers


1
Điều này là quá đáng!
DrB

15

http://site.mockito.org/mockito/docs/1.10.19/org/mockito/Matchers.html

anyObject() nên phù hợp với nhu cầu của bạn.

Ngoài ra, bạn luôn có thể xem xét thực hiện hashCode()equals()cho Bazoolớp. Điều này sẽ làm cho ví dụ mã của bạn hoạt động theo cách bạn muốn.


Đồng ý với đề xuất thứ hai, nhưng tôi vẫn chọn không làm điều đó vì lý do phi kỹ thuật.
Eric Wilson

1
Lớp Matchers không được dùng nữa (xem tài liệu - "Lớp này có thể sẽ bị xóa trong phiên bản 3.0" )
Johannes Rabauer

1

Một lựa chọn khác là dựa vào equalsphương pháp thời trang cũ tốt . Miễn là đối số trong whengiả equalslập đối số trong mã đang được kiểm tra, thì Mockito sẽ khớp với giả định.

Đây là một ví dụ.

public class MyPojo {

    public MyPojo( String someField ) {
        this.someField = someField;
    }

    private String someField;

    @Override
    public boolean equals( Object o ) {
        if ( this == o ) return true;
        if ( o == null || getClass() != o.getClass() ) return false;
        MyPojo myPojo = ( MyPojo ) o;
        return someField.equals( myPojo.someField );
    }

}

sau đó, giả sử bạn biết giá trị của someFieldnó sẽ là bao nhiêu, bạn có thể chế giễu nó như thế này.

when(fooDao.getBar(new MyPojo(expectedSomeField))).thenReturn(myFoo);

ưu điểm: Điều này rõ ràng hơn anyso sánh. Là một người đánh giá mã, tôi để mắt tới anycác nhà phát triển cơ sở viết mã, vì nó lướt qua logic của mã của họ để tạo ra đối tượng thích hợp được thông qua.

con: Đôi khi trường được truyền cho đối tượng là một ID ngẫu nhiên. Trong trường hợp này, bạn không thể dễ dàng xây dựng đối tượng đối số dự kiến ​​trong mã giả của mình.

Một cách tiếp cận khả thi khác là sử dụng Answerđối tượng của Mockito có thể được sử dụng với whenphương thức. Answercho phép bạn chặn cuộc gọi thực tế và kiểm tra đối số đầu vào và trả về một đối tượng giả. Trong ví dụ dưới đây, tôi đang sử dụng anyđể bắt bất kỳ yêu cầu nào đối với phương thức bị chế giễu. Nhưng sau đó trong Answerlambda, tôi có thể kiểm tra thêm đối số Bazo ... có thể để xác minh rằng một ID thích hợp đã được chuyển cho nó. Tôi thích điều này hơn anychính nó để ít nhất một số kiểm tra được thực hiện trên đối số.

    Bar mockBar = //generate mock Bar.

    when(fooDao.getBar(any(Bazo.class))
    .thenAnswer(  ( InvocationOnMock invocationOnMock) -> {
        Bazo actualBazo = invocationOnMock.getArgument( 0 );

        //inspect the actualBazo here and thrw exception if it does not meet your testing requirements.
        return mockBar;
    } );

Vì vậy, để tổng hợp tất cả, tôi thích dựa vào equals(trong đó đối số dự kiến ​​và đối số thực tế phải bằng nhau) và nếu không thể bằng nhau (do không thể dự đoán trạng thái của đối số thực tế), tôi sẽ dùng đến để Answerkiểm tra lập luận.

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.