Perbandingan antara Mockito vs JMockit - Mengapa Mockito terpilih lebih baik daripada JMockit? [Tutup]

124

Saya sedang menyelidiki kerangka kerja tiruan mana yang akan digunakan untuk proyek saya dan telah mempersempitnya ke JMockit dan Mockito .

Saya melihat bahwa Mockito terpilih sebagai " kerangka kerja tiruan terbaik untuk Java " di Stackoverflow.
Dalam membandingkan fitur di JMockit 's ' Mocking Alat perbandingan Matrix ' tampak bahwa JMockit memiliki beberapa fitur yang berbeda.

Apakah ada yang punya informasi khusus (bukan opini) tentang apa yang dapat dilakukan Mockito yang tidak dapat dicapai dengan JMockit dan sebaliknya?

Rogério
sumber
2
mungkin kegunaan yang lebih baik untuk mockito, btw saya tidak berpikir JMockit lebih dewasa dari Mockito ...
Alois Cochard
42
Dilihat dari jumlah suara, JELAS jawaban atas pertanyaan ini sangat dicari oleh masyarakat. Artinya, strategi ortogonalisasi situs ini yang menyebabkan pertanyaan ini ditutup memerlukan pemikiran ulang yang serius - dalam hal ini situs ini sering menginjakkan kaki untuk dapat memberikan jawaban yang dibutuhkan dengan jatuh pada ortogonalitas yang tidak selaras. Tidak menyadari bahwa dalam analisis grafik pohon, ada banyak cara untuk melihat ortogonalitas pohon sebanyak node. Mungkin ortogonalitas situs ini, bukan pertanyaannya, tidak selaras.
Blessed Geek
9
1 untuk tidak menutup. Jawaban-jawaban ini sangat berharga. Memilih teknologi tidaklah mudah dan pertanyaan-pertanyaan ini dapat menghemat banyak waktu. Memang mungkin tidak ada jawaban yang benar, tetapi StackOverflow harus mengakomodasi pertanyaan tanpa jawaban.
mhstnsc
6
Saya akan menambahkan dukungan saya kepada mereka yang menyatakan bahwa menutup ini sebagai "tidak membangun" adalah konyol. Jawaban yang diberikan di sini didukung oleh "fakta, referensi, dan / atau keahlian". Sebuah pertanyaan dalam dunia teknologi yang tidak menimbulkan "debat, jajak pendapat, atau diskusi panjang" biasanya hampir tidak layak untuk ditanyakan. Lebih lanjut, memberikan fakta dan keahlian bergantung pada pengalaman yang berbeda - dan perbedaan tersebut akan mengarah pada perdebatan dan diskusi yang diperpanjang.
Jeff Nyman
@Alois - dapatkah Anda memberikan contoh konkret di mana JMockit terlihat kurang dewasa daripada Mockito?
NitinS

Jawaban:

140

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:

  1. Setiap kelas yang mungkin perlu diolok-olok dalam pengujian harus mengimplementasikan antarmuka terpisah atau belum final.
  2. 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.
  3. 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.

Hendy Irawan
sumber
1
Saya tidak pernah menggunakan jmockit, tetapi saya ingin menambahkan argumen lain ke diskusi: lihat perbandingan tren google dari semua kerangka kerja yang dibahas. Pada 06.06.2012, JMockit bahkan tidak muncul di grafik tren google jika dibandingkan dengan Mockito dan EasyMock. Dan jumlah pengguna juga penting saat memilih kerangka kerja.
mesin
3
Itu sangat aneh. Mockito dan JMockIt memberi saya masing-masing 409 'dan 83' hits di google. Tentunya JMockIt harus muncul setidaknya.
thoredge
5
Jawaban Anda sangat membantu. Saya berencana untuk menggunakan Mockito saja, tetapi sekarang saya akan menguji JMockit terlebih dahulu. Kedengarannya bagus untuk tidak mencobanya. @Mesin: Ya, penting untuk melihat tren, tetapi memilihnya sebagai kriteria utama akan membatasi Anda ke arus utama dan melindungi Anda dari inovasi.
deamon
1
Saya tahu ini adalah utas lama, tetapi setelah membaca ulasan ini saya pikir saya akan mencobanya juga. Saya harus mengatakan, di permukaan, JMockit sangat menjanjikan. Namun, hingga saat ini, saya merasa dukungan masyarakat sangat kurang. Saya mengalami masalah besar dengan pemahaman saya tentang Mock API dan setelah memposting masalah saya, saya tidak mendapat tanggapan dalam 2 hari.
Eric B.
1
Jawabannya adalah 8 tahun, jadi banyak hal di jawaban ini yang tidak lebih benar. Satu poin adalah bahwa JMockit memerlukan -javaagentflag sejak 1.42 karena Anda tidak dapat melampirkan sendiri lagi sejak Java 9 dan menemukan solusi yang sesuai jelas tidak berada dalam lingkup pengembang. Poin lain adalah bahwa JMockit tidak mengizinkan lagi untuk meniru metode dan konstruktor privat sementara PowerMock melakukannya.
Vampir
24

Saya bekerja dengan Mockito dan JMockit, dan pengalaman saya dengan mereka adalah:

  • Mockito:

    • ejekan implisit (-> kegunaan yang lebih baik, tetapi berisiko gagal mendeteksi panggilan metode yang tidak diizinkan pada tiruan)
    • verifikasi eksplisit
  • EasyMock:

    • jelaskan mengejek
    • verifikasi implisit
  • JMockit:

    • mendukung keduanya
  • Selain itu, manfaat lain dari JMockit:

    • jika Anda mengejek metode / konstruktor statis dll (seperti memperluas basis kode warisan yang sangat lama tanpa UT), Anda akan memiliki dua pilihan: 1) Mockito / EasyMock dengan ekstensi Powermock atau 2) Jmockit
    • laporan cakupan bawaan

Saya pribadi lebih suka JMockit, yang menurut saya lebih kaya fitur dan fleksibel, tetapi membutuhkan kurva pembelajaran yang sedikit lebih curam. Biasanya ada beberapa cara untuk mencapai efek mengejek yang sama, dan membutuhkan lebih banyak perhatian saat mendesain tiruan.

Tumer
sumber
ada stackoverflow.com/questions/8003278/… "verifikasiNoMoreInteractions" Saya kira jika Anda ingin ejekan pseudo eksplisit dengan mockito
rogerdpack
15

Saya menggunakan jMockit hanya karena perpustakaan refleksi di Deencapsultation.class. Saya sebenarnya menyukai gaya Mockito, tetapi saya menolak untuk mengubah kode saya dan memperkeruh API saya hanya agar kerangka pengujian terbatas dapat melakukannya. Dan saya penggemar pengujian semua kode saya, jadi kerangka kerja yang tidak dapat dengan mudah menguji metode pribadi bukanlah yang ingin saya gunakan.

Saya terpengaruh oleh artikel ini

Setelah kurva pembelajaran (yang diakui besar), jMockit sekarang menjadi kerangka kerja pengujian unit utama saya untuk tiruan.

Joseph Erickson
sumber
7
Mungkin jika Anda merasa perlu menguji metode privat, Anda terlalu khawatir dengan cara kerja kode Anda, daripada dengan apa yang dilakukannya (yang merupakan poin sebenarnya, dan yang dapat ditentukan hanya dengan menjalankan metode publiknya). Juga, saya akan tertarik untuk membaca artikel itu, tetapi tautannya rusak.
kode
4 tahun kemudian, apakah Anda masih menggunakan jMockit sebagai framework pengujian utama Anda? Saya mencobanya untuk pertama kalinya dan mengalami beberapa masalah dengannya, tetapi saya tidak tahu apakah saya salah paham tentang cara kerja jMockit, atau apakah itu fitur yang tidak ada.
Eric B.
jMockit tidak lagi mendukung pengujian metode pribadi. Kelas Deencapsulation perlahan-lahan tidak digunakan lagi dan kemudian dihapus seluruhnya dalam versi 1.47. jmockit.github.io/changes.html
Pytry
4

Untuk pengujian mudah basis kode lama kami (dengan banyak panggilan metode statis, dll.), JMockit sangat berharga. [Steker tak tahu malu untuk artikel di blog saya]

Jeff Olson
sumber
0

Saya pribadi lebih suka EasyMock .
Kemampuan untuk mengalihkan antara kontrol ejekan yang bagus, normal, dan ketat adalah salah satu fitur favorit saya.

Bivas
sumber