Ini pendekatan saya. Ini memiliki biaya dalam hal waktu karena merupakan tes refactor dalam 4 fase.
Apa yang akan saya paparkan mungkin cocok dengan komponen yang lebih rumit daripada yang terpapar dalam contoh pertanyaan.
Bagaimanapun strategi tersebut valid untuk setiap kandidat komponen yang dinormalisasi dengan antarmuka (DAO, Layanan, Pengendali, ...).
1. Antarmuka
Mari kita kumpulkan semua metode publik dari MyDocumentService dan mari kita satukan semuanya menjadi sebuah antarmuka. Misalnya. Jika sudah ada, gunakan yang itu daripada mengatur yang baru .
public interface DocumentService {
List<Document> getAllDocuments();
//more methods here...
}
Kemudian kami memaksa MyDocumentService untuk mengimplementasikan antarmuka baru ini.
Sejauh ini bagus. Tidak ada perubahan besar yang dilakukan, kami menghormati kontrak saat ini dan behaivos tetap tidak tersentuh.
public class MyDocumentService implements DocumentService {
@Override
public List<Document> getAllDocuments(){
//legacy code here as it is.
// with no changes ...
}
}
2. Tes unit kode warisan
Di sini kita memiliki kerja keras. Untuk mengatur test suite. Kita harus menetapkan sebanyak mungkin kasus: kasus sukses dan juga kasus kesalahan. Yang terakhir ini untuk kebaikan kualitas hasil.
Sekarang, alih-alih menguji MyDocumentService kita akan menggunakan antarmuka sebagai kontrak yang akan diuji.
Saya tidak akan masuk ke rincian, jadi maafkan saya Jika kode saya terlihat terlalu sederhana atau terlalu agnostik
public class DocumentServiceTestSuite {
@Mock
MyDependencyA mockDepA;
@Mock
MyDependencyB mockDepB;
//... More mocks
DocumentService service;
@Before
public void initService(){
service = MyDocumentService(mockDepA, mockDepB);
//this is purposed way to inject
//dependencies. Replace it with one you like more.
}
@Test
public void getAllDocumentsOK(){
// here I mock depA and depB
// wanted behaivors...
List<Document> result = service.getAllDocuments();
Assert.assertX(result);
Assert.assertY(result);
//... As many you think appropiate
}
}
Tahap ini membutuhkan waktu lebih lama daripada yang lain dalam pendekatan ini. Dan itu yang paling penting karena akan menetapkan titik referensi untuk perbandingan di masa depan.
Catatan: Karena tidak ada perubahan besar yang dibuat dan behaivor tetap tidak tersentuh. Saya sarankan untuk melakukan tag di sini ke SCM. Tag atau cabang tidak masalah. Lakukan saja versi.
Kami menginginkannya untuk rollbacks, perbandingan versi dan mungkin untuk eksekusi paralel dari kode lama dan yang baru.
3. Refactoring
Refactor akan diimplementasikan menjadi komponen baru. Kami tidak akan melakukan perubahan pada kode yang ada. Langkah pertama semudah melakukan copy & paste MyDocumentService dan ganti namanya menjadi CustomDocumentService (misalnya).
Kelas baru terus menerapkan DocumentService . Lalu pergi dan refactorize getAllDocuments () . (Mari kita mulai dengan satu. Pin-refactor)
Mungkin memerlukan beberapa perubahan pada antarmuka / metode DAO. Jika demikian, jangan ubah kode yang ada. Terapkan metode Anda sendiri di antarmuka DAO. Kode lama Annotate sebagai Usang dan Anda akan tahu nanti apa yang harus dihapus.
Sangat penting untuk tidak merusak / mengubah implementasi yang ada. Kami ingin menjalankan kedua layanan secara paralel dan kemudian membandingkan hasilnya.
public class CustomDocumentService implements DocumentService {
@Override
public List<Document> getAllDocuments(){
//new code here ...
//due to im refactoring service
//I do the less changes possible on its dependencies (DAO).
//these changes will come later
//and they will have their own tests
}
}
4. Memperbarui DocumentServiceTestSuite
Ok, sekarang bagian yang lebih mudah. Untuk menambah tes komponen baru.
public class DocumentServiceTestSuite {
@Mock
MyDependencyA mockDepA;
@Mock
MyDependencyB mockDepB;
DocumentService service;
DocumentService customService;
@Before
public void initService(){
service = MyDocumentService(mockDepA, mockDepB);
customService = CustomDocumentService(mockDepA, mockDepB);
// this is purposed way to inject
//dependencies. Replace it with the one you like more
}
@Test
public void getAllDocumentsOK(){
// here I mock depA and depB
// wanted behaivors...
List<Document> oldResult = service.getAllDocuments();
Assert.assertX(oldResult);
Assert.assertY(oldResult);
//... As many you think appropiate
List<Document> newResult = customService.getAllDocuments();
Assert.assertX(newResult);
Assert.assertY(newResult);
//... The very same made to oldResult
//this is optional
Assert.assertEquals(oldResult,newResult);
}
}
Sekarang kita memiliki oldResult dan newResult keduanya divalidasi secara independen tetapi kita juga dapat membandingkan satu sama lain. Validasi terakhir ini bersifat opsional dan tergantung pada hasilnya. Mungkin itu tidak sebanding.
Mungkin tidak membuat terlalu banyak seity untuk membandingkan dua koleksi dengan cara ini, tetapi akan berlaku untuk objek jenis lain (pojos, entitas model data, DTO, Pembungkus, tipe asli ...)
Catatan
Saya tidak akan berani memberi tahu bagaimana melakukan tes unit atau cara menggunakan lib mock. Saya tidak berani mengatakan bagaimana Anda harus melakukan refactor. Yang ingin saya lakukan adalah menyarankan strategi global. Cara membawanya tergantung pada Anda. Anda tahu persis bagaimana kode itu, kompleksitasnya dan apakah strategi seperti itu patut dicoba. Fakta seperti waktu dan sumber daya penting di sini. Juga penting apa yang Anda harapkan dari tes ini di masa depan.
Saya telah memulai contoh saya dengan Layanan dan saya akan mengikuti dengan DAO dan seterusnya. Masuk jauh ke tingkat ketergantungan. Kurang lebih bisa digambarkan sebagai strategi dari atas ke bawah . Namun untuk perubahan kecil / refaktor ( seperti yang terlihat pada contoh tur ), bottom up akan melakukan tugas dengan lebih mudah. Karena ruang lingkup perubahannya sedikit.
Akhirnya, terserah Anda untuk menghapus kode yang sudah usang dan untuk mengalihkan dependensi lama ke yang baru.
Hapus juga tes yang sudah usang dan pekerjaan sudah selesai. Jika Anda memberi versi solusi lama dengan pengujiannya, Anda dapat memeriksa dan membandingkan satu sama lain kapan saja.
Karena begitu banyak pekerjaan, Anda memiliki kode lama diuji, divalidasi, dan versi. Dan kode baru, diuji, divalidasi, dan siap diversi.