Jawabannya ada di dokumentasi :
Parsial nyata (Sejak 1.8.0)
Akhirnya, setelah banyak debat & diskusi internal di milis, dukungan tiruan parsial ditambahkan ke Mockito. Sebelumnya kami menganggap olok-olok parsial sebagai bau kode. Namun, kami menemukan kasus penggunaan yang sah untuk tiruan sebagian.
Sebelum rilis 1.8 spy () tidak menghasilkan tiruan parsial yang nyata dan itu membingungkan bagi beberapa pengguna. Baca lebih lanjut tentang mata-mata: di sini atau di javadoc untuk metode mata-mata (Objek).
callRealMethod()
diperkenalkan setelahnya spy()
, tetapi spy () ditinggalkan di sana tentu saja, untuk memastikan kompatibilitas ke belakang.
Jika tidak, Anda benar: semua metode mata-mata adalah nyata kecuali jika dihentikan. Semua metode tiruan dihentikan kecuali callRealMethod()
dipanggil. Secara umum, saya lebih suka menggunakan callRealMethod()
, karena tidak memaksa saya menggunakan doXxx().when()
idiom daripada tradisionalwhen().thenXxx()
Perbedaan antara Spy dan Mock
Saat Mockito membuat tiruan - ia melakukannya dari Class of a Type, bukan dari instance sebenarnya. Tiruan itu hanya membuat contoh shell tanpa tulang dari Kelas, yang sepenuhnya diinstrumentasi untuk melacak interaksi dengannya. Di sisi lain, mata-mata akan membungkus contoh yang ada. Ini akan tetap berperilaku dengan cara yang sama seperti contoh normal - satu-satunya perbedaan adalah bahwa itu juga akan diinstrumentasi untuk melacak semua interaksi dengannya.
Dalam contoh berikut - kami membuat tiruan kelas ArrayList:
@Test public void whenCreateMock_thenCreated() { List mockedList = Mockito.mock(ArrayList.class); mockedList.add("one"); Mockito.verify(mockedList).add("one"); assertEquals(0, mockedList.size()); }
Seperti yang Anda lihat - menambahkan elemen ke dalam daftar tiruan sebenarnya tidak menambahkan apa-apa - itu hanya memanggil metode tanpa efek samping lain. Di sisi lain, mata-mata akan berperilaku berbeda - ia akan memanggil implementasi sebenarnya dari metode add dan menambahkan elemen ke daftar yang mendasarinya:
@Test public void whenCreateSpy_thenCreate() { List spyList = Mockito.spy(new ArrayList()); spyList.add("one"); Mockito.verify(spyList).add("one"); assertEquals(1, spyList.size()); }
Di sini kita pasti dapat mengatakan bahwa metode internal sebenarnya dari objek dipanggil karena ketika Anda memanggil metode size () Anda mendapatkan ukuran sebagai 1, tetapi metode size () ini tidak diejek! Jadi darimana saya berasal? Metode internal real size () disebut size () tidak diejek (atau distub) dan karenanya kita dapat mengatakan bahwa entri telah ditambahkan ke objek nyata.
Sumber: http://www.baeldung.com/mockito-spy + catatan diri.
sumber
mockedList.size()
kembali0
jika metode itu belum dimatikan juga? Apakah itu hanya nilai default yang diberikan tipe kembalian dari metode ini?mockedList.size()
mengembalikanint
nilai default danint
adalah 0 di Java. Jika Anda mencoba mengeksekusiassertEquals(0, mockedList.size());
setelahnyamockedList.clear();
, hasilnya tetap sama.Jika ada objek dengan 8 metode dan Anda memiliki pengujian di mana Anda ingin memanggil 7 metode nyata dan metode rintisan satu Anda memiliki dua opsi:
spy
Anda harus mengaturnya dengan mematikan satu metodeThe dokumentasi resmi pada
doCallRealMethod
merekomendasikan menggunakan mata-mata untuk mengolok-olok parsial.sumber
Spy dapat berguna ketika Anda ingin membuat tes unit untuk kode lama .
Saya telah membuat contoh yang dapat dijalankan di sini https://www.surasint.com/mockito-with-spy/ , saya menyalin sebagian di sini.
Jika Anda memiliki sesuatu seperti kode ini:
public void transfer( DepositMoneyService depositMoneyService, WithdrawMoneyService withdrawMoneyService, double amount, String fromAccount, String toAccount){ withdrawMoneyService.withdraw(fromAccount,amount); depositMoneyService.deposit(toAccount,amount); }
Anda mungkin tidak perlu memata-matai karena Anda hanya dapat meniru DepositMoneyService dan WithdrawMoneyService.
Tetapi dengan beberapa, kode lama, ketergantungan ada dalam kode seperti ini:
public void transfer(String fromAccount, String toAccount, double amount){ this.depositeMoneyService = new DepositMoneyService(); this.withdrawMoneyService = new WithdrawMoneyService(); withdrawMoneyService.withdraw(fromAccount,amount); depositeMoneyService.deposit(toAccount,amount); }
Ya, Anda dapat mengubah ke kode pertama tetapi kemudian API diubah. Jika metode ini digunakan di banyak tempat, Anda harus mengubah semuanya.
Alternatifnya adalah Anda dapat mengekstrak dependensi seperti ini:
public void transfer(String fromAccount, String toAccount, double amount){ this.depositeMoneyService = proxyDepositMoneyServiceCreator(); this.withdrawMoneyService = proxyWithdrawMoneyServiceCreator(); withdrawMoneyService.withdraw(fromAccount,amount); depositeMoneyService.deposit(toAccount,amount); } DepositMoneyService proxyDepositMoneyServiceCreator() { return new DepositMoneyService(); } WithdrawMoneyService proxyWithdrawMoneyServiceCreator() { return new WithdrawMoneyService(); }
Kemudian Anda dapat menggunakan mata-mata untuk menyuntikkan ketergantungan seperti ini:
DepositMoneyService mockDepositMoneyService = mock(DepositMoneyService.class); WithdrawMoneyService mockWithdrawMoneyService = mock(WithdrawMoneyService.class); TransferMoneyService target = spy(new TransferMoneyService()); doReturn(mockDepositMoneyService) .when(target).proxyDepositMoneyServiceCreator(); doReturn(mockWithdrawMoneyService) .when(target).proxyWithdrawMoneyServiceCreator();
Lebih detail ada di tautan di atas.
sumber
[Uji tipe ganda]
Mock
vs.Spy
Mock
adalah objek ganda yang telanjang. Objek ini memiliki tanda tangan metode yang sama tetapi realisasinya kosong dan mengembalikan nilai default - 0 dan nullSpy
adalah objek ganda hasil kloning. Objek baru diklon berdasarkan objek nyata tetapi Anda memiliki kemungkinan untuk mengejeknyaclass A { String foo1() { foo2(); return "RealString_1"; } String foo2() { return "RealString_2"; } void foo3() { foo4(); } void foo4() { } }
@Test public void testMockA() { //given A mockA = Mockito.mock(A.class); Mockito.when(mockA.foo1()).thenReturn("MockedString"); //when String result1 = mockA.foo1(); String result2 = mockA.foo2(); //then assertEquals("MockedString", result1); assertEquals(null, result2); //Case 2 //when mockA.foo3(); //then verify(mockA).foo3(); verify(mockA, never()).foo4(); } @Test public void testSpyA() { //given A spyA = Mockito.spy(new A()); Mockito.when(spyA.foo1()).thenReturn("MockedString"); //when String result1 = spyA.foo1(); String result2 = spyA.foo2(); //then assertEquals("MockedString", result1); assertEquals("RealString_2", result2); //Case 2 //when spyA.foo3(); //then verify(spyA).foo3(); verify(spyA).foo4(); }
sumber