Bagaimana cara memverifikasi bahwa metode tertentu tidak dipanggil menggunakan Mockito?


626

Bagaimana cara memverifikasi bahwa suatu metode tidak dipanggil pada ketergantungan objek?

Sebagai contoh:

public interface Dependency {
    void someMethod();
}

public class Foo {
    public bar(final Dependency d) {
        ...
    }
}

Dengan tes Foo:

public class FooTest {
    @Test
    public void dependencyIsNotCalled() {
        final Foo foo = new Foo(...);
        final Dependency dependency = mock(Dependency.class);
        foo.bar(dependency);
        **// verify here that someMethod was not called??**
    }
}

Jawaban:


1088

Yang lebih bermakna:

import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

// ...

verify(dependency, never()).someMethod();

Dokumentasi fitur ini ada §4 "Memverifikasi jumlah persis doa / setidaknya x / tidak pernah" , dan neverjavadoc ada di sini .


144
Menggunakan neveradalah cara terbaik dan paling spesifik, tetapi jika Anda perlu memeriksa seluruh objek tiruan, pertimbangkan juga verifyZeroInteractions(mockObject)atau verifyNoMoreInteractions(mockObject).
Jeff Bowman

apa yang harus dilakukan jika beberapa metode pribadi ??
Sumit Kumar Saha

1
Maka Anda tidak dapat mengejeknya di tempat pertama (dengan Mockito);) PowerMock memungkinkan untuk itu tetapi lebih rumit untuk diatur. Atau jika Anda memiliki kode tersebut, Anda dapat mengendurkan visibilitas ke paket.
Brice

2
Sejak 3.0.1 verifyZeroInteractionstelah ditinggalkan. verifyNoInteractions adalah alternatif yang disarankan. Versi Mockito pada saat komentar ini adalah 3.3.3
VKB

108

gunakan argumen kedua pada Mockito.verifymetode, seperti pada:

verify(dependency, Mockito.times(0)).someMethod()


11
public VerificationMode statis tidak pernah () {kembali kali (0); }
gbero

3
never()tidak secara signifikan lebih mudah dibaca daripada times(0). Tetapi keberadaan nevermemang meningkatkan beban kognitif dan membuat sistem mockito lebih sulit untuk memahami dan mengingat cara menggunakannya. Jadi mockito benar-benar seharusnya tidak termasuk neverdalam API mereka, itu tidak sebanding dengan biaya mental.
BT

Pertanyaan: apakah formulir ini memverifikasi yang someMethoddipanggil 0 kali, atau apakah hanya memverifikasi yang someMethodtidak pernah dipanggil dengan argumen nol?
BT

@ Bt - Saya akan membayangkan memverifikasi someMethoddengan argumen nol disebut nol kali - tidak diverifikasi.
beluchin

18

Sebagai pola yang lebih umum untuk diikuti, saya cenderung menggunakan @Afterblok dalam tes:

@After
public void after() {
    verifyNoMoreInteractions(<your mock1>, <your mock2>...);
}

Maka tes bebas untuk memverifikasi hanya apa yang harus dipanggil.

Juga, saya menemukan bahwa saya sering lupa untuk memeriksa "tidak ada interaksi", hanya untuk kemudian menemukan bahwa hal-hal sedang dipanggil yang seharusnya.

Jadi saya menemukan pola ini berguna untuk menangkap semua panggilan tak terduga yang belum secara khusus diverifikasi.


9
Dokumentasi Mockito menyatakan bahwa pola ini tidak boleh disalahgunakan - "Kata peringatan: Beberapa pengguna yang melakukan banyak ejekan klasik, jalankan-verifikasi cenderung menggunakan verifikasiNoMoreInteractions () sangat sering, bahkan dalam setiap metode pengujian. VerifikasiNoMoreInteractions () tidak disarankan untuk digunakan dalam setiap metode pengujian. verifikasiNoMoreInteractions () adalah pernyataan praktis dari toolkit pengujian interaksi. Gunakan hanya jika relevan. Menyalahgunakan itu mengarah pada pengujian yang terlalu ditentukan dan kurang dipelihara. " Lihat di sini
Chadi

2
"Gunakan hanya ketika itu relevan". Saya merasa selalu relevan. Saya tidak melihat pola itu sebagai pelecehan: seperti yang saya katakan, ia menemukan "hal-hal yang disebut tidak seharusnya terjadi". Bagi saya, itu adalah verifikasi yang sangat penting: jika ada sesuatu yang memanggil repositori yang seharusnya tidak digunakan, saya ingin mengetahuinya! Kecuali ada cara lain untuk memverifikasi itu tanpa menggunakan verifyNoMoreInteractions? Jawaban lain di sini bergantung pada penulis tes yang secara eksplisit mengingat untuk mencantumkan cek ini: terlalu rentan kesalahan dalam buku saya.
David Lavender

2
Saya melihat komentar ini, tetapi juga merasa bahwa alasannya tidak meyakinkan. Saya ingin membaca lebih lanjut tentang mengapa ini tidak dianjurkan.
tobinibot

2
@tobinibot Karena gagasan pengujian unit adalah untuk memverifikasi suatu Kontrak. Sebagian besar kontrak biasanya tidak melibatkan berapa kali beberapa metode lain dipanggil, tetapi lebih dari itu melalui parameter yang diketahui menghasilkan respons yang dikenal. Dengan tidak menggunakan lagi interaksi, Anda pada dasarnya memverifikasi implementasi baris demi baris, yang membuat refactoring dan implementasi menjadi membosankan. Yang bukan titik pengujian unit.
Andrew T Finnell

8

Pertama-tama: Anda harus selalu mengimpor mockito statis, dengan cara ini kode akan jauh lebih mudah dibaca (dan intuitif):

import static org.mockito.Mockito.*;

Sebenarnya ada banyak cara untuk mencapai ini, namun (bisa dibilang) lebih bersih untuk menggunakan

verify(yourMock, times(0)).someMethod();

metode di seluruh tes Anda, ketika pada Tes lain Anda menggunakannya untuk menyatakan sejumlah eksekusi seperti ini:

verify(yourMock, times(5)).someMethod();

Alternatifnya adalah:

verify(yourMock, never()).someMethod();

Atau - ketika Anda benar-benar ingin memastikan Objek yang diejek sebenarnya TIDAK disebut sama sekali - Anda dapat menggunakan:

verifyZeroInteractions(yourMock)

7

Baik metode verifyNoMoreInteractions()maupun secara verifyZeroInteractions()internal memiliki implementasi yang sama seperti:

public static transient void verifyNoMoreInteractions(Object mocks[])
{
    MOCKITO_CORE.verifyNoMoreInteractions(mocks);
}

public static transient void verifyZeroInteractions(Object mocks[])
{
    MOCKITO_CORE.verifyNoMoreInteractions(mocks);
}

jadi kita bisa menggunakan salah satu dari mereka pada objek tiruan atau array objek tiruan untuk memeriksa bahwa tidak ada metode yang dipanggil menggunakan objek tiruan.

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.