Bagaimana saya dapat membuat tiruan variabel bidang yang sedang diinisialisasi?
class Test {
private Person person = new Person();
...
public void testMethod() {
person.someMethod();
...
}
}
Di sini saya ingin mengejek person.someMethod()
saat menguji Test.testMethod()
metode yang saya perlukan untuk meniru inisialisasi person
variabel. Ada petunjuk?
Edit: Saya tidak diizinkan untuk mengubah kelas Person.
java
mockito
junit4
powermockito
Arun
sumber
sumber
Person
. Opsi termasuk menambahkan konstruktor untuk melakukan ini, atau menambahkan metode penyetel.Jawaban:
Mockito hadir dengan kelas pembantu untuk menghemat beberapa kode pelat boiler refleksi:
import org.mockito.internal.util.reflection.Whitebox; //... @Mock private Person mockedPerson; private Test underTest; // ... @Test public void testMethod() { Whitebox.setInternalState(underTest, "person", mockedPerson); // ... }
Pembaruan: Sayangnya tim mockito memutuskan untuk menghapus kelas di Mockito 2. Jadi Anda kembali menulis kode boilerplate refleksi Anda sendiri, gunakan pustaka lain (misalnya Apache Commons Lang ), atau cukup mencuri kelas Whitebox (itu berlisensi MIT ).
Pembaruan 2: JUnit 5 hadir dengan kelas ReflectionSupport dan AnnotationSupport -nya sendiri yang mungkin berguna dan menyelamatkan Anda dari menarik perpustakaan lain.
sumber
internal
paketnya dan sepertinya tidak berfungsi lagi di Mockito 2.6.2.Cukup terlambat ke pesta, tapi saya terpukul di sini dan mendapat bantuan dari seorang teman. Masalahnya adalah tidak menggunakan PowerMock. Ini berfungsi dengan versi terbaru Mockito.
Mockito datang dengan ini
org.mockito.internal.util.reflection.FieldSetter
.Apa yang pada dasarnya dilakukannya adalah membantu Anda mengubah bidang pribadi menggunakan refleksi.
Inilah cara Anda menggunakannya:
@Mock private Person mockedPerson; private Test underTest; // ... @Test public void testMethod() { FieldSetter.setField(underTest, underTest.getClass().getDeclaredField("person"), mockedPerson); // ... verify(mockedPerson).someMethod(); }
Dengan cara ini Anda bisa melewatkan objek tiruan dan kemudian memverifikasinya nanti.
Berikut referensinya.
sumber
FieldSetter
tidak tersedia lagi di Mockito 2.x.Class#getDeclaredField
menerima parameter tunggal, jadi orang tua harus terlihat seperti iniFieldSetter.setField(underTest, underTest.getClass().getDeclaredField("person"), mockedPerson);
. Begitulah cara saya salah dan berpikir mungkin ide yang bagus untuk memperbaikinya dalam contoh Anda. Terima kasih sudah membalas.Jika Anda menggunakan Uji Musim Semi, coba org.springframework.test.util.ReflectionTestUtils
ReflectionTestUtils.setField(testObject, "person", mockedPerson);
sumber
testImplementation("org.springframework:spring-test:5.1.2.RELEASE")
Saya sudah menemukan solusi untuk masalah ini yang saya lupa posting di sini.
@RunWith(PowerMockRunner.class) @PrepareForTest({ Test.class }) public class SampleTest { @Mock Person person; @Test public void testPrintName() throws Exception { PowerMockito.whenNew(Person.class).withNoArguments().thenReturn(person); Test test= new Test(); test.testMethod(); } }
Poin utama dari solusi ini adalah:
Menjalankan kasus pengujian saya dengan PowerMockRunner:
@RunWith(PowerMockRunner.class)
Perintahkan Powermock untuk mempersiapkan
Test.class
manipulasi bidang pribadi:@PrepareForTest({ Test.class })
Dan akhirnya mengejek konstruktor untuk kelas Person:
PowerMockito.mockStatic(Person.class);
PowerMockito.whenNew(Person.class).withNoArguments().thenReturn(person);
sumber
mockStatic
fungsi tersebut, tetapi itu tidak terwakili dalam contoh kode Anda. Haruskah contoh kode memilikimockStatic
panggilan, atau apakah itu tidak diperlukan untuk konstruktor?Kode berikut dapat digunakan untuk menginisialisasi mapper di mock klien REST. The
mapper
bidang pribadi dan harus ditetapkan selama setup unit tes.import org.mockito.internal.util.reflection.FieldSetter; new FieldSetter(client, Client.class.getDeclaredField("mapper")).set(new Mapper());
sumber
Menggunakan panduan @ Jarda, Anda dapat menentukan ini jika Anda perlu menyetel variabel dengan nilai yang sama untuk semua pengujian:
@Before public void setClientMapper() throws NoSuchFieldException, SecurityException{ FieldSetter.setField(client, client.getClass().getDeclaredField("mapper"), new Mapper()); }
Namun berhati-hatilah bahwa menetapkan nilai pribadi menjadi berbeda harus ditangani dengan hati-hati. Jika mereka pribadi karena alasan tertentu.
Contoh, saya menggunakannya, misalnya, untuk mengubah waktu tunggu tidur di unit test. Dalam contoh nyata saya ingin tidur selama 10 detik tetapi dalam unit-test saya puas jika langsung. Dalam pengujian integrasi, Anda harus menguji nilai sebenarnya.
sumber