mockito callback dan mendapatkan nilai argumen

89

Saya tidak beruntung mendapatkan Mockito untuk menangkap nilai argumen fungsi! Saya mengejek indeks mesin pencari dan alih-alih membuat indeks, saya hanya menggunakan hash.

// Fake index for solr
Hashmap<Integer,Document> fakeIndex;

// Add a document 666 to the fakeIndex
SolrIndexReader reader = Mockito.mock(SolrIndexReader.class);

// Give the reader access to the fake index
Mockito.when(reader.document(666)).thenReturn(document(fakeIndex(666))

Saya tidak dapat menggunakan argumen sewenang-wenang karena saya sedang menguji hasil kueri (yaitu dokumen mana yang dikembalikan). Demikian juga, saya tidak ingin menentukan nilai tertentu dan memiliki garis untuk setiap dokumen!

Mockito.when(reader.document(0)).thenReturn(document(fakeIndex(0))
Mockito.when(reader.document(1)).thenReturn(document(fakeIndex(1))
....
Mockito.when(reader.document(n)).thenReturn(document(fakeIndex(n))

Saya melihat bagian panggilan balik di halaman Menggunakan Mockito . Sayangnya, ini bukan Java dan saya tidak bisa mendapatkan interpretasi saya sendiri tentang itu untuk bekerja di Java.

EDIT (untuk klarifikasi): Bagaimana cara membuat Mockito menangkap argumen X dan meneruskannya ke fungsi saya? Saya ingin nilai pasti (atau ref) dari X diteruskan ke fungsi.

Saya tidak ingin menghitung semua kasus, dan argumen sewenang-wenang tidak akan berfungsi karena saya menguji hasil yang berbeda untuk kueri yang berbeda.

Halaman Mockito mengatakan

val mockedList = mock[List[String]]
mockedList.get(anyInt) answers { i => "The parameter is " + i.toString } 

Itu bukan java, dan saya tidak tahu cara menerjemahkan ke dalam java atau meneruskan apa pun yang terjadi menjadi suatu fungsi.

nflacco
sumber
Saya tidak yakin saya mengerti persis apa yang gagal untuk Anda. Panggilan Anda ke Mockito.when(reader.document(666)).thenReturn(document(fakeIndex(666))harus menyiapkan objek tiruan untuk Anda. Apa yang terjadi saat Anda menelepon reader.document(666)?
berkafein tinggi
666 bekerja dengan baik. Namun, saya ingin meneruskan angka X tertentu dan mendapatkan hasil dari fakeIndex (X). Saya memiliki sejumlah besar dokumen potensial untuk diuji kueri, dan saya tidak ingin memasukkan semuanya.
nflacco

Jawaban:

104

Saya tidak pernah menggunakan Mockito, tetapi ingin belajar, jadi ini dia. Jika seseorang yang kurang mengerti dariku menjawab, coba jawaban mereka dulu!

Mockito.when(reader.document(anyInt())).thenAnswer(new Answer() {
 public Object answer(InvocationOnMock invocation) {
     Object[] args = invocation.getArguments();
     Object mock = invocation.getMock();
     return document(fakeIndex((int)(Integer)args[0]));
     }
 });
Ed Staub
sumber
2
Saya baru saja melihat tautan di sisi kanan ke Mockito: Cara membuat metode mengembalikan argumen yang diteruskan padanya . Sepertinya aku dekat, jika tidak tepat.
Ed Staub
reputasi pengguna yang kuat (666) terhadap korelasi pertanyaan asli! Itu bekerja dengan sangat baik. Hanya perubahan yang saya buat untuk mendapatkan kompilasi barang yang dipublikasikan di depan jawaban Object (seruan InvocationOnMock) ....
nflacco
54

Lihat ArgumentCaptors:

https://site.mockito.org/javadoc/current/org/mockito/ArgumentCaptor.html

ArgumentCaptor<Integer> argument = ArgumentCaptor.forClass(Integer.class);
Mockito.when(reader.document(argument.capture())).thenAnswer(
  new Answer() {
    Object answer(InvocationOnMock invocation) {
      return document(argument.getValue());
    }
  });
kualidafial
sumber
3
Wow, aku tidak tahu kamu bisa menggunakan ArgumentCaptors untuk stubbing. Ada peringatan besar tentang itu di tautan itu. Lanjutkan dengan hati hati.
einnocent
3
Ya, Anda benar. Penculik hanya boleh digunakan dengan verifikasi.
qualidafial
41

Anda mungkin ingin menggunakan verifikasi () dalam kombinasi dengan ArgumentCaptor untuk memastikan eksekusi dalam pengujian dan ArgumentCaptor untuk mengevaluasi argumen:

ArgumentCaptor<Document> argument = ArgumentCaptor.forClass(Document.class);
verify(reader).document(argument.capture());
assertEquals(*expected value here*, argument.getValue());

Nilai argumen jelas dapat diakses melalui argument.getValue () untuk manipulasi / pemeriksaan lebih lanjut atau apa pun yang ingin Anda lakukan.

fl0w
sumber
2
jawaban terbaik: lurus ke depan, mudah dimengerti
Radu Cugut
Tidak menjawab pertanyaan itu. Pertanyaannya tentang Mockito.when dan tidak memverifikasi.
seBaka28
@ seBaka28 solusi terbaik untuk mendapatkan argumen adalah penangkap argumen. ArgumentCaptors sangat disarankan untuk digunakan dengan verifikasi oleh penulis Mockito, oleh karena itu saya ingin memberikan jawaban perspektif lengkap. jika Anda sendiri memilih untuk tidak menggunakannya, itu adalah pilihan Anda, tetapi tidak disarankan. EDIT: Saya tidak melihat bagaimana ini membenarkan downvote, tapi itu juga pilihan Anda.
fl0w
1
Karena tidak menjawab pertanyaan tersebut. Ya, ArgumentCaptor sangat bagus ketika Anda ingin menangkap argumen, tetapi Anda tidak dapat menggunakannya bersama dengan when (...). ThenReturn () yang OP coba lakukan: Berdasarkan parameter tertentu, layanan tiruan seharusnya mengembalikan objek tertentu.
seBaka28
1
@YuraHoy itu adalah pesan kesalahan standar saat Anda menggunakan verifikasi dan objek atau metode dipanggil lebih sering daripada yang Anda katakan untuk verifikasi. Anda dapat mengubah jumlah ekspektasi dengan menambahkan argumen times (n) sebagai berikut: verifikasi (reader, times (5)) - ini akan mengharapkan 5 interaksi. Untuk referensi silakan lihat: baeldung.com/mockito-verify
fl0w
14

Dengan Java 8, ini bisa menjadi seperti ini:

Mockito.when(reader.document(anyInt())).thenAnswer(
  (InvocationOnMock invocation) -> document(invocation.getArguments()[0]));

Saya berasumsi bahwa itu documentadalah peta.

Jean-François Beauchef
sumber