Menggunakan metode “any ()” generik Mockito


194

Saya memiliki antarmuka dengan metode yang mengharapkan array Foo:

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

Saya mengejek antarmuka ini menggunakan Mockito, dan saya ingin menegaskan yang doStuff()dipanggil, tapi saya tidak ingin memvalidasi argumen apa yang diloloskan - "tidak peduli".

Bagaimana cara menulis kode berikut menggunakan any() , metode generik, bukan anyObject()?

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

Jawaban:


111

Karena Java 8 Anda dapat menggunakan metode argumen-kurang anydan argumen tipe akan disimpulkan oleh kompiler:

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

Penjelasan

Hal baru di Java 8 adalah bahwa tipe target ekspresi akan digunakan untuk menyimpulkan parameter tipe sub-ekspresi. Sebelum Java 8 hanya argumen untuk metode yang digunakan untuk tipe inferensi parameter (sebagian besar waktu).

Dalam hal ini tipe parameter doStuffakan menjadi tipe target untuk any(), dan tipe nilai pengembalian any()akan dipilih untuk mencocokkan tipe argumen itu.

Mekanisme ini ditambahkan di Java 8 terutama untuk dapat mengkompilasi ekspresi lambda, tetapi umumnya meningkatkan inferensi tipe.


Tipe primitif

Sayangnya, ini tidak berfungsi dengan tipe primitif:

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

Masalahnya adalah bahwa kompiler akan menyimpulkan Integersebagai nilai balik dari any(). Mockito tidak akan mengetahui hal ini (karena tipe penghapusan) dan mengembalikan nilai default untuk tipe referensi, yaitu null. Runtime akan mencoba untuk membuka kotak nilai kembali dengan memanggil intValuemetode di atasnya sebelum meneruskannya doStuff, dan pengecualian dilemparkan.


Saya terkejut setiap kali jawaban ini mendapat dukungan! Saya akan menduga bahwa pertanyaan itu tidak akan menarik banyak perhatian sejak Java 8, karena anymetode ini seharusnya hanya bekerja. Anda tidak mencari jawaban untuk hal-hal yang hanya berfungsi!
Lii

Saya datang ke sini karena saya tidak tahu mengapa kode saya tidak bekerja any()tetapi tidak apa-apa anyBoolean(), yang bagian terakhir dari jawaban Anda menjelaskan dengan indah.
AdrienW

274

Ini seharusnya bekerja

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

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

31
kalau-kalau seseorang membutuhkannya di Scala:verify(bar).DoStuff(any[Array[Foo]])
tolitius

6
Saya punya masalah dengan impor, saya menggunakan any () dari hamcrest di impor saya dan bertabrakan dengan yang dari mockito.
Doppelganger

4
Silakan lihat API, argumen kelas hanya digunakan untuk casting, metode ini masih menerima objek apa pun! situs.mockito.org/mockito/docs/current/org/mockito/… . Gunakan isA () untuk case case ini situs.mockito.org/mockito/docs/current/org/mockito/… .
thilko

1
Kelas ini sekarang tidak digunakan lagi untuk menghindari bentrokan nama dengan Hamcrest. Gunakan org.mockito.ArgumentMatchers
leo9r

12

Anda dapat menggunakannya Mockito.isA()untuk itu:

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

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

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


Ini jawaban yang benar. Menggunakan salah satu (Clazz) sepenuhnya salah.
Surasin Tancharoen

3
@SurasinTancharoen Sebenarnya, setiap (Kelas) hanyalah alias dari isA (Kelas) (lihat dokumen). Jadi sama sekali tidak salah.
jmiserez

8

Karena saya perlu menggunakan fitur ini untuk proyek terbaru saya (pada satu titik kami memperbarui dari 1.10.19), hanya agar pengguna (yang sudah menggunakan mockito-core versi 2.1.0 atau lebih tinggi ) tetap up to date, statis metode dari jawaban di atas harus diambil dari ArgumentMatcherskelas:

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

Ingatlah hal ini jika Anda berencana untuk memperbarui artefak Mockito Anda mulai dari versi 3, kelas ini mungkin tidak ada lagi:

Per 2.1.0 dan lebih tinggi, Javadoc dari org.mockito.Matchers menyatakan:

Gunakan org.mockito.ArgumentMatchers. Kelas ini sekarang tidak digunakan lagi untuk menghindari bentrokan nama dengan org.hamcrest.Matchers kelas Hamcrest * . Kelas ini kemungkinan akan dihapus dalam versi 3.0.

Saya telah menulis sedikit artikel tentang wildcard mockito jika Anda siap untuk membaca lebih lanjut.


Bagaimana saya bisa mengimpor org.mockito.ArgumentMatcher di Scala? Saya mencoba mengimpor org.mockito.ArgumentMatcher.any Saya mendapatkan nilai kesalahan `tidak ada anggota objek org.mockito.ArgumentMatcher
Manu Chadha

Bisakah Anda memberi tahu saya apa yang setara di versi 3.0?
Manu Chadha

Kita akan tahu begitu itu akan dirilis;)
Maciej Kowalski
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.