Saya sarankan Anda sedikit refactoring kode Anda. Ketika Anda harus mulai berpikir tentang menggunakan refleksi atau hal-hal lain, untuk hanya menguji kode Anda, ada yang salah dengan kode Anda.
Anda menyebutkan berbagai jenis masalah. Mari kita mulai dengan bidang pribadi. Dalam kasus bidang pribadi saya akan menambahkan konstruktor baru dan menyuntikkan bidang ke dalamnya. Alih-alih ini:
public class ClassToTest {
private final String first = "first";
private final List<String> second = new ArrayList<>();
...
}
Saya akan menggunakan ini:
public class ClassToTest {
private final String first;
private final List<String> second;
public ClassToTest() {
this("first", new ArrayList<>());
}
public ClassToTest(final String first, final List<String> second) {
this.first = first;
this.second = second;
}
...
}
Ini tidak akan menjadi masalah bahkan dengan beberapa kode lawas. Kode lama akan menggunakan konstruktor kosong, dan jika Anda bertanya kepada saya, kode refactored akan terlihat lebih bersih, dan Anda akan dapat menyuntikkan nilai yang diperlukan dalam pengujian tanpa refleksi.
Sekarang tentang metode pribadi. Dalam pengalaman pribadi saya ketika Anda harus mematikan metode pribadi untuk pengujian, maka metode itu tidak ada hubungannya di kelas itu. Pola umum, dalam hal ini, adalah membungkusnya dalam sebuah antarmuka, seperti Callable
dan kemudian Anda memasukkan antarmuka itu juga dalam konstruktor (dengan beberapa trik konstruktor):
public ClassToTest() {
this(...);
}
public ClassToTest(final Callable<T> privateMethodLogic) {
this.privateMethodLogic = privateMethodLogic;
}
Kebanyakan yang saya tulis sepertinya merupakan pola injeksi ketergantungan. Dalam pengalaman pribadi saya, ini sangat berguna saat pengujian, dan saya pikir kode semacam ini lebih bersih dan lebih mudah dirawat. Saya akan mengatakan hal yang sama tentang kelas bersarang. Jika kelas bersarang mengandung logika berat, akan lebih baik jika Anda memindahkannya sebagai paket kelas privat dan telah menyuntikkannya ke kelas yang membutuhkannya.
Ada juga beberapa pola desain lain yang telah saya gunakan saat refactoring dan mempertahankan kode lama, tetapi semuanya tergantung pada kasus kode Anda untuk diuji. Menggunakan refleksi sebagian besar bukan masalah, tetapi ketika Anda memiliki aplikasi perusahaan yang sangat diuji dan tes dijalankan sebelum setiap penyebaran semuanya menjadi sangat lambat (itu hanya mengganggu dan saya tidak suka hal-hal semacam itu).
Ada juga injeksi setter, tetapi saya tidak akan merekomendasikan menggunakannya. Saya lebih baik tetap dengan konstruktor dan menginisialisasi semuanya ketika itu benar-benar diperlukan, meninggalkan kemungkinan untuk menyuntikkan dependensi yang diperlukan.