Perbarui Sep 2019: Satu-satunya kerangka kerja tiruan yang didukung (secara default) oleh Spring Boot adalah Mockito . Jika Anda menggunakan Spring, jawabannya cukup jelas.
Menurut saya, persaingannya adalah antara JMockit dan PowerMock , lalu Mockito .
Saya akan meninggalkan jMock dan EasyMock "biasa" karena mereka hanya menggunakan proxy & CGLIB dan tidak menggunakan instrumentasi Java 5 seperti kerangka kerja yang lebih baru.
jMock juga tidak memiliki rilis stabil selama lebih dari 4 tahun. jMock 2.6.0 membutuhkan waktu 2 tahun untuk beralih dari RC1 ke RC2, dan kemudian 2 tahun lagi sebelum benar-benar dirilis.
Mengenai Proxy & CGLIB vs instrumentasi:
(EasyMock dan jMock) didasarkan pada java.lang.reflect.Proxy, yang membutuhkan antarmuka untuk diimplementasikan. Selain itu, mereka mendukung pembuatan objek tiruan untuk kelas melalui pembuatan subkelas CGLIB. Karena itu, kelas tersebut tidak dapat bersifat final dan hanya metode instance yang dapat diganti yang dapat dibuat tiruan. Yang paling penting, bagaimanapun, saat menggunakan alat ini, ketergantungan kode yang diuji (yaitu, objek kelas lain yang menjadi tempat bergantung kelas tertentu yang diuji) harus dikontrol oleh pengujian, sehingga contoh tiruan dapat diteruskan ke klien. dependensi tersebut. Oleh karena itu, dependensi tidak bisa begitu saja dibuat instance-nya dengan operator baru di kelas klien yang ingin kita tulis pengujian unitnya.
Pada akhirnya, batasan teknis alat tiruan konvensional memberlakukan batasan desain berikut pada kode produksi:
- Setiap kelas yang mungkin perlu diolok-olok dalam pengujian harus mengimplementasikan antarmuka terpisah atau belum final.
- Dependensi setiap kelas yang akan diuji harus diperoleh melalui metode pembuatan instans yang dapat dikonfigurasi (pabrik atau Service Locator), atau diekspos untuk injeksi ketergantungan. Jika tidak, pengujian unit tidak akan dapat meneruskan implementasi tiruan dependensi ke unit yang diuji.
- Karena hanya metode instance yang dapat dibuat tiruan, kelas yang akan diuji unit tidak dapat memanggil metode statis apa pun pada dependensinya, atau membuat instance menggunakan salah satu konstruktor.
Di atas disalin dari http://jmockit.org/about.html . Lebih lanjut, ini membandingkan antara dirinya sendiri (JMockit), PowerMock, dan Mockito dalam beberapa cara:
Sekarang ada alat mocking lain untuk Java yang juga mengatasi keterbatasan alat konvensional, di antaranya PowerMock, jEasyTest, dan MockInject. Salah satu yang paling mendekati kumpulan fitur JMockit adalah PowerMock, jadi saya akan mengevaluasinya secara singkat di sini (selain itu, dua lainnya lebih terbatas dan sepertinya tidak dikembangkan secara aktif lagi).
JMockit vs PowerMock
- Pertama-tama, PowerMock tidak menyediakan API lengkap untuk pembuatan tiruan, tetapi berfungsi sebagai ekstensi untuk alat lain, yang saat ini dapat berupa EasyMock atau Mockito. Ini jelas merupakan keuntungan bagi pengguna alat tersebut yang sudah ada.
- JMockit, di sisi lain, menyediakan API yang sama sekali baru, meskipun API (Harapan) utamanya mirip dengan EasyMock dan jMock. Meskipun hal ini menciptakan kurva pembelajaran yang lebih panjang, ini juga memungkinkan JMockit menyediakan API yang lebih sederhana, lebih konsisten, dan lebih mudah digunakan.
- Dibandingkan dengan JMockit Expectations API, PowerMock API lebih "tingkat rendah", memaksa pengguna untuk mencari tahu dan menentukan kelas mana yang perlu disiapkan untuk pengujian (dengan anotasi @PrepareForTest ({ClassA.class, ...}) ) dan memerlukan panggilan API khusus untuk menangani berbagai jenis konstruksi bahasa yang mungkin ada dalam kode produksi: metode statis (mockStatic (ClassA.class)), konstruktor (penekan (konstruktor (ClassXyz.class))), pemanggilan konstruktor ( expectNew (AClass.class)), tiruan sebagian (createP PartialMock (ClassX.class, "methodToMock")), dll.
- Dengan JMockit Expectations, semua jenis metode dan konstruktor diejek dengan cara yang murni deklaratif, dengan ejekan parsial yang ditentukan melalui ekspresi reguler di anotasi @Mocked atau hanya dengan "tidak mengejek" anggota tanpa ekspektasi yang terekam; yaitu, pengembang cukup mendeklarasikan beberapa "bidang tiruan" bersama untuk kelas pengujian, atau beberapa "bidang tiruan lokal" dan / atau "parameter tiruan" untuk masing-masing metode pengujian (dan dalam kasus terakhir ini anotasi @Mocked sering tidak dibutuhkan).
- Beberapa kemampuan yang tersedia di JMockit, seperti dukungan untuk mocking equals dan hashCode, metode yang diganti, dan lainnya, saat ini tidak didukung di PowerMock. Selain itu, tidak ada yang setara dengan kemampuan JMockit untuk menangkap instance dan implementasi tiruan dari tipe dasar yang ditentukan saat pengujian dijalankan, tanpa kode pengujian itu sendiri yang memiliki pengetahuan tentang kelas implementasi yang sebenarnya.
- PowerMock menggunakan pemuat kelas kustom (biasanya satu per kelas pengujian) untuk menghasilkan versi kelas tiruan yang dimodifikasi. Penggunaan berat pemuat kelas khusus seperti itu dapat menyebabkan konflik dengan pustaka pihak ketiga, oleh karena itu terkadang perlu menggunakan anotasi @PowerMockIgnore ("package.to.be.ignored") pada kelas pengujian.
- Mekanisme yang digunakan oleh JMockit (instrumentasi runtime melalui "agen Java") lebih sederhana dan lebih aman, meskipun itu memang memerlukan penerusan parameter "-javaagent" ke JVM saat mengembangkan di JDK 1.5; pada JDK 1.6+ (yang selalu dapat digunakan untuk pengembangan, meskipun menerapkan pada versi yang lebih lama) tidak ada persyaratan seperti itu, karena JMockit dapat secara transparan memuat agen Java sesuai permintaan dengan menggunakan API Lampirkan.
Alat mengejek terbaru lainnya adalah Mockito. Meskipun tidak mencoba untuk mengatasi batasan alat yang lebih lama (jMock, EasyMock), itu memperkenalkan gaya baru pengujian perilaku dengan tiruan. JMockit juga mendukung gaya alternatif ini, melalui API Verifikasi.
JMockit vs Mockito
- Mockito mengandalkan panggilan eksplisit ke API-nya untuk memisahkan kode antara fase rekaman (saat (...)) dan verifikasi (verifikasi (...)). Artinya, setiap pemanggilan ke objek tiruan dalam kode pengujian juga akan memerlukan panggilan ke API tiruan. Selain itu, ini akan sering menyebabkan pengulangan saat (...) dan verifikasi (tiruan) ... panggilan.
- Dengan JMockit, tidak ada panggilan serupa. Tentu, kami memiliki panggilan konstruktor NonStrictExpectations () dan Verifications () baru, tetapi panggilan tersebut hanya terjadi sekali per pengujian (biasanya), dan sepenuhnya terpisah dari pemanggilan ke metode dan konstruktor tiruan.
- API Mockito berisi beberapa ketidakkonsistenan dalam sintaks yang digunakan untuk pemanggilan ke metode palsu. Dalam fase rekam, kami memiliki panggilan seperti when (mock.mockedMethod (args)) ... sedangkan dalam fase verifikasi panggilan yang sama ini akan ditulis sebagai verifikasi (mock) .mockedMethod (args). Perhatikan bahwa dalam kasus pertama pemanggilan ke mockedMethod dibuat langsung pada objek tiruan, sedangkan pada kasus kedua pemanggilan dibuat pada objek yang dikembalikan oleh verifikasi (mock).
- JMockit tidak memiliki inkonsistensi seperti itu karena pemanggilan ke metode tiruan selalu dibuat langsung pada instance yang dibuat-buat itu sendiri. (Hanya dengan satu pengecualian: untuk mencocokkan pemanggilan pada instance palsu yang sama, panggilan onInstance (tiruan) digunakan, menghasilkan kode seperti onInstance (mock) .mockedMethod (args); namun, sebagian besar pengujian tidak perlu menggunakan ini. )
- Sama seperti alat mocking lain yang mengandalkan metode perangkaian / pembungkusan, Mockito juga mengalami sintaks yang tidak konsisten saat menghentikan metode void. Misalnya, Anda menulis when (mockedList.get (1)). ThenThrow (new RuntimeException ()); untuk metode non-void, dan doThrow (new RuntimeException ()). when (mockedList) .clear (); untuk yang kosong. Dengan JMockit, sintaksnya selalu sama: mockedList.clear (); result = new RuntimeException () ;.
- Namun ketidakkonsistenan lain terjadi dalam penggunaan mata-mata Mockito: "tiruan" yang memungkinkan metode nyata untuk dieksekusi pada contoh mata-mata. Misalnya, jika spy merujuk ke List kosong, alih-alih menulis when (spy.get (0)). ThenReturn ("foo") Anda perlu menulis doReturn ("foo"). When (spy) .get ( 0). Dengan JMockit, fitur tiruan dinamis menyediakan fungsionalitas yang mirip dengan mata-mata, tetapi tanpa masalah ini karena metode nyata hanya dijalankan selama fase replay.
- Di EasyMock dan jMock, API tiruan pertama untuk Java, fokusnya sepenuhnya pada pencatatan permintaan yang diharapkan dari metode tiruan, untuk objek tiruan yang (secara default) tidak mengizinkan pemanggilan yang tidak terduga. API tersebut juga menyediakan rekaman pemanggilan yang diizinkan untuk objek tiruan yang memungkinkan pemanggilan tak terduga, tetapi ini diperlakukan sebagai fitur kelas dua. Selain itu, dengan alat ini tidak ada cara untuk memverifikasi secara eksplisit pemanggilan untuk tiruan setelah kode yang diuji dijalankan. Semua verifikasi tersebut dilakukan secara implisit dan otomatis.
- Di Mockito (dan juga di Unitils Mock), sudut pandang yang berlawanan diambil. Semua pemanggilan untuk objek tiruan yang mungkin terjadi selama pengujian, baik direkam atau tidak, diperbolehkan, tidak pernah diharapkan. Verifikasi dilakukan secara eksplisit setelah kode yang diuji dijalankan, tidak pernah secara otomatis.
- Kedua pendekatan tersebut terlalu ekstrim sehingga kurang optimal. JMockit Expectations & Verifications adalah satu-satunya API yang memungkinkan pengembang untuk dengan mulus memilih kombinasi terbaik dari pemanggilan palsu ketat (diharapkan secara default) dan non-ketat (diizinkan secara default) untuk setiap pengujian.
- Untuk lebih jelasnya, API Mockito memiliki kekurangan sebagai berikut. Jika Anda perlu memverifikasi bahwa pemanggilan ke metode tiruan non-void terjadi selama pengujian, tetapi pengujian tersebut memerlukan nilai kembalian dari metode tersebut yang berbeda dari default untuk tipe kembalian, maka pengujian Mockito akan memiliki kode duplikat: ketika (mock.someMethod ()). thenReturn (xyz) memanggil dalam fase rekam, dan verifikasi (tiruan) .someMethod () dalam fase verifikasi. Dengan JMockit, ekspektasi yang ketat selalu dapat direkam, yang tidak harus diverifikasi secara eksplisit. Alternatifnya, batasan jumlah pemanggilan (times = 1) dapat ditentukan untuk ekspektasi non-ketat yang direkam (dengan Mockito batasan tersebut hanya dapat ditentukan dalam panggilan verifikasi (tiruan, batasan)).
- Mockito memiliki sintaksis yang buruk untuk verifikasi secara berurutan, dan untuk verifikasi penuh (yaitu, memeriksa bahwa semua pemanggilan ke objek tiruan diverifikasi secara eksplisit). Dalam kasus pertama, objek tambahan perlu dibuat, dan panggilan untuk memverifikasi dibuat di atasnya: InOrder inOrder = inOrder (mock1, mock2, ...). Dalam kasus kedua, panggilan seperti verifikasiNoMoreInteractions (tiruan) atau verifikasiZeroInteractions (mock1, mock2) perlu dilakukan.
- Dengan JMockit, Anda cukup menulis VerificationsInOrder () baru atau FullVerifications () baru alih-alih Verifications () baru (atau FullVerificationsInOrder () baru untuk menggabungkan kedua persyaratan). Tidak perlu menentukan objek tiruan mana yang terlibat. Tidak ada panggilan API tambahan yang mengejek. Dan sebagai bonus, dengan memanggil unverifiedInvocations () di dalam blok verifikasi yang dipesan, Anda dapat melakukan verifikasi terkait pesanan yang tidak mungkin dilakukan di Mockito.
Terakhir, JMockit Testing Toolkit memiliki cakupan yang lebih luas dan tujuan yang lebih ambisius daripada toolkit tiruan lainnya, untuk memberikan solusi pengujian pengembang yang lengkap dan canggih. API yang baik untuk mengejek, bahkan tanpa batasan buatan, tidak cukup untuk pembuatan pengujian yang produktif. Alat Cakupan Kode yang agnostik IDE, mudah digunakan, dan terintegrasi dengan baik juga penting, dan itulah tujuan dari JMockit Coverage. Bagian lain dari perangkat pengujian pengembang yang akan menjadi lebih berguna seiring bertambahnya ukuran rangkaian pengujian adalah kemampuan untuk menjalankan ulang pengujian secara bertahap setelah perubahan lokal pada kode produksi; ini juga termasuk dalam alat Cakupan.
(memang, sumbernya mungkin bias, tapi yah ...)
Saya akan mengatakan pergi dengan JMockit . Ini paling mudah digunakan, fleksibel, dan berfungsi untuk hampir semua kasus bahkan yang sulit dan skenario ketika Anda tidak dapat mengontrol kelas yang akan diuji (atau Anda tidak dapat merusaknya karena alasan kompatibilitas, dll.).
Pengalaman saya dengan JMockit sangat positif.