Sử dụng phương pháp chung bất kỳ () của Mockito


194

Tôi có một giao diện với một phương thức mong đợi một mảng Foo:

public interface IBar {
  void doStuff(Foo[] arr);
}

Tôi đang chế giễu giao diện này bằng Mockito và tôi muốn khẳng định rằng nó doStuff()được gọi, nhưng tôi không muốn xác thực đối số nào được thông qua - "không quan tâm".

Làm thế nào để tôi viết đoạn mã sau bằng cách sử dụng any()phương thức chung thay vì anyObject()?

IBar bar = mock(IBar.class);
...
verify(bar).doStuff((Foo[]) anyObject());

Câu trả lời:


111

Vì Java 8, bạn có thể sử dụng anyphương thức không có đối số và đối số kiểu sẽ được trình biên dịch suy ra:

verify(bar).doStuff(any());

Giải trình

Điều mới trong Java 8 là kiểu đích của một biểu thức sẽ được sử dụng để suy ra các tham số kiểu của các biểu thức con của nó. Trước Java 8 chỉ đối số với các phương thức được sử dụng cho suy luận tham số kiểu (hầu hết thời gian).

Trong trường hợp này, loại tham số doStuffsẽ là loại mục tiêu any()và loại giá trị trả về any()sẽ được chọn để khớp với loại đối số đó.

Cơ chế này đã được thêm vào trong Java 8 chủ yếu để có thể biên dịch các biểu thức lambda, nhưng nó cải thiện suy luận kiểu nói chung.


Các loại nguyên thủy

Điều này không hoạt động với các loại nguyên thủy, không may:

public interface IBar {
    void doPrimitiveStuff(int i);
}

verify(bar).doPrimitiveStuff(any()); // Compiles but throws NullPointerException
verify(bar).doPrimitiveStuff(anyInt()); // This is what you have to do instead

Vấn đề là trình biên dịch sẽ suy ra Integergiá trị trả về của any(). Mockito sẽ không nhận thức được điều này (do loại xóa) và trả về giá trị mặc định cho các loại tham chiếu null. Thời gian chạy sẽ cố gắng bỏ hộp giá trị trả về bằng cách gọi intValuephương thức trên nó trước khi chuyển đến doStuffvà ngoại lệ được đưa ra.


Tôi rất ngạc nhiên mỗi khi câu trả lời này nhận được một upvote! Tôi đã đoán rằng câu hỏi sẽ không thu hút nhiều sự chú ý kể từ Java 8, vì anyphương thức này chỉ hoạt động. Bạn không tìm kiếm câu trả lời cho những thứ chỉ hoạt động!
Lii

Tôi đến đây vì tôi không biết tại sao mã của tôi không hoạt động any()nhưng vẫn ổn anyBoolean(), phần cuối cùng trong câu trả lời của bạn làm sáng tỏ một cách tuyệt vời.
AdrienW

274

Điều này sẽ làm việc

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;

verify(bar).DoStuff(any(Foo[].class));

31
chỉ trong trường hợp ai đó cần nó ở Scala:verify(bar).DoStuff(any[Array[Foo]])
Tolican

6
Tôi gặp vấn đề với việc nhập, tôi đang sử dụng bất kỳ () nào từ hamcrest trong hàng nhập khẩu của mình và nó đã va chạm với hàng nhập từ mockito.
Doppelganger

4
Xin hãy xem API, đối số lớp chỉ được sử dụng để truyền, phương thức vẫn chấp nhận bất kỳ loại đối tượng nào! site.mockito.org/mockito/docs/civerse/org/mockito/ ,. Sử dụng isA () cho trường hợp này site.mockito.org/mockito/docs/civerse/org/mockito/ .
thilko

1
Lớp này hiện không được dùng nữa để tránh xung đột tên với Hamcrest. Sử dụng org.mockito.ArgumentMatchers
leo9r

12

Bạn có thể sử dụng Mockito.isA()cho điều đó:

import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.verify;

verify(bar).doStuff(isA(Foo[].class));

http://site.mockito.org/mockito/docs/cản/org/mockito/Matchers.html#isA(java.lang.Class)


Đây là câu trả lời chính xác. Sử dụng bất kỳ (Clazz) là hoàn toàn sai.
Surasin Tancharoen

3
@SurasinTancharoen Trên thực tế, bất kỳ (Lớp) nào cũng chỉ là bí danh của isA (Lớp) (xem tài liệu). Vì vậy, nó không sai.
jmiserez

8

Vì tôi cần sử dụng tính năng này cho dự án mới nhất của mình (tại một thời điểm chúng tôi đã cập nhật từ 1.10.19), chỉ để giữ cho người dùng (đã sử dụng phiên bản mockito-core 2.1.0 trở lên), tĩnh phương pháp từ các câu trả lời trên nên được lấy từ ArgumentMatcherslớp:

import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.ArgumentMatchers.any;

Hãy ghi nhớ điều này nếu bạn dự định cập nhật các đồ tạo tác Mockito của mình vì có thể bắt đầu từ phiên bản 3, lớp này có thể không còn tồn tại:

Theo 2.1.0 trở lên, Javadoc của org.mockito.Matchers tuyên bố:

Sử dụng org.mockito.ArgumentMatchers. Lớp này hiện không được dùng nữa để tránh xung đột tên với org.hamcrest.Matchers lớp Hamcrest * . Lớp này có thể sẽ bị xóa trong phiên bản 3.0.

Tôi đã viết một bài viết nhỏ về ký tự đại diện mockito nếu bạn muốn đọc thêm.


Làm cách nào tôi có thể nhập org.mockito.ArgumentMatcher trong Scala? Tôi cố gắng nhập khẩu org.mockito.ArgumentMatcher.any tôi nhận được lỗi `giá trị bất kỳ không phải là thành viên của đối tượng org.mockito.ArgumentMatcher
Manu Chadha

Bạn có thể vui lòng cho tôi biết tương đương trong phiên bản 3.0 là gì không?
Manu Chadha

Chúng ta sẽ biết một khi nó sẽ được phát hành;)
Maciej Kowalski
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.