Panduan untuk ReflectionTestUtils untuk Pengujian Unit

1. Perkenalan

ReflectionTestUtils adalah bagian dari kerangka Konteks Uji Musim Semi. Ini adalah kumpulan metode utilitas berbasis refleksi yang digunakan dalam sebuah unit, dan skenario pengujian integrasi untuk menyetel bidang non-publik, memanggil metode non-publik, dan menyuntikkan dependensi.

Dalam tutorial ini, kita akan melihat bagaimana kita dapat menggunakan ReflectionTestUtils dalam pengujian unit dengan melalui beberapa contoh.

2. Ketergantungan Maven

Mari kita mulai dengan menambahkan versi terbaru dari semua dependensi yang diperlukan untuk contoh kita ke pom.xml kita :

 org.springframework spring-context 5.1.2.RELEASE   org.springframework spring-test 5.1.2.RELEASE test 

Dependensi uji pegas konteks pegas terbaru dapat diunduh dari repositori Pusat Maven.

3. Menggunakan ReflectionTestUtils untuk Menetapkan Nilai Bidang Non-Publik

Misalkan kita perlu menggunakan turunan dari kelas yang memiliki bidang privat tanpa metode penyetel publik dalam pengujian unit kami.

Mari kita mulai dengan membuatnya:

public class Employee { private Integer id; private String name; // standard getters/setters }

Biasanya kami tidak dapat mengakses id bidang privat untuk menetapkan nilai untuk pengujian, karena tidak ada metode penyetel publik untuk itu.

Kita kemudian dapat menggunakan metode ReflectionTestUtils.setField untuk menetapkan nilai ke id anggota pribadi :

@Test public void whenNonPublicField_thenReflectionTestUtilsSetField() { Employee employee = new Employee(); ReflectionTestUtils.setField(employee, "id", 1); assertTrue(employee.getId().equals(1)); }

4. Menggunakan ReflectionTestUtils untuk Memanggil Metode Non-Publik

Sekarang mari kita bayangkan bahwa kita memiliki metode private employeeToString di kelas Employee :

private String employeeToString(){ return "id: " + getId() + "; name: " + getName(); }

Kita dapat menulis pengujian unit untuk metode employeeToString seperti di bawah ini, meskipun tidak memiliki akses apa pun dari luar kelas Employee :

@Test public void whenNonPublicMethod_thenReflectionTestUtilsInvokeMethod() { Employee employee = new Employee(); ReflectionTestUtils.setField(employee, "id", 1); employee.setName("Smith, John"); assertTrue(ReflectionTestUtils.invokeMethod(employee, "employeeToString") .equals("id: 1; name: Smith, John")); }

5. Menggunakan ReflectionTestUtils untuk Menyuntikkan Dependensi

Misalkan Anda ingin menulis pengujian unit untuk komponen Spring berikut yang memiliki bidang privat dengan anotasi @Autowired :

@Component public class EmployeeService { @Autowired private HRService hrService; public String findEmployeeStatus(Integer employeeId) { return "Employee " + employeeId + " status: " + hrService.getEmployeeStatus(employeeId); } }

Sekarang kita dapat mengimplementasikan komponen HRService seperti di bawah ini:

@Component public class HRService { public String getEmployeeStatus(Integer employeeId) { return "Inactive"; } }

Selanjutnya, mari buat implementasi tiruan untuk kelas HRService dengan menggunakan Mockito. Kami akan memasukkan tiruan ini ke dalam instance EmployeeService , dan kami akan menggunakannya dalam pengujian unit kami:

HRService hrService = mock(HRService.class); when(hrService.getEmployeeStatus(employee.getId())).thenReturn("Active");

Karena hrService adalah bidang pribadi tanpa penyetel publik, kami akan menggunakan metode ReflectionTestUtils.setField untuk memasukkan tiruan yang kami buat di atas ke dalam bidang pribadi ini.

EmployeeService employeeService = new EmployeeService(); ReflectionTestUtils.setField(employeeService, "hrService", hrService);

Akhirnya, pengujian unit kami akan terlihat seperti ini:

@Test public void whenInjectingMockOfDependency_thenReflectionTestUtilsSetField() { Employee employee = new Employee(); ReflectionTestUtils.setField(employee, "id", 1); employee.setName("Smith, John"); HRService hrService = mock(HRService.class); when(hrService.getEmployeeStatus(employee.getId())).thenReturn("Active"); EmployeeService employeeService = new EmployeeService(); // Inject mock into the private field ReflectionTestUtils.setField(employeeService, "hrService", hrService); assertEquals( "Employee " + employee.getId() + " status: Active", employeeService.findEmployeeStatus(employee.getId())); }

Kita harus mencatat bahwa teknik ini adalah solusi untuk fakta bahwa kita menggunakan injeksi lapangan di kelas kacang kita. Jika kita beralih ke injeksi konstruktor maka pendekatan ini tidak diperlukan.

6. Kesimpulan

Dalam tutorial ini, kami menunjukkan cara menggunakan ReflectionTestUtils dalam pengujian unit dengan melalui beberapa contoh.

Contoh kode, seperti biasa, dapat ditemukan di Github.