JMockit 101

1. Perkenalan

Dengan artikel ini, kami akan memulai seri baru yang berpusat di sekitar JMockit toolkit mocking.

Dalam angsuran pertama ini kita akan berbicara tentang apa itu JMockit, karakteristiknya dan bagaimana tiruan dibuat dan digunakan dengannya.

Artikel selanjutnya akan fokus dan membahas lebih dalam tentang kemampuannya.

2. JMockit

2.1. pengantar

Pertama-tama, mari kita bicara tentang apa itu JMockit: kerangka kerja Java untuk mengejek objek dalam pengujian (Anda dapat menggunakannya untuk JUnit dan TestNG).

Ini menggunakan API instrumentasi Java untuk memodifikasi bytecode kelas selama runtime untuk mengubah perilakunya secara dinamis. Beberapa kelebihannya adalah ekspresibilitas dan kemampuannya yang luar biasa untuk meniru metode statis dan privat.

Mungkin Anda baru mengenal JMockit, tetapi itu pasti bukan karena itu baru. Pengembangan JMockit dimulai pada Juni 2006 dan tanggal rilis stabil pertama hingga Desember 2012, jadi sudah ada untuk beberapa waktu sekarang (versi saat ini adalah 1,24 pada saat menulis artikel).

2.2. Ketergantungan Maven

Pertama, kita perlu menambahkan ketergantungan jmockit ke proyek kita:

 org.jmockit jmockit 1.41 

2.3. Ekspresibilitas JMockit

Seperti yang diceritakan sebelumnya, salah satu poin terkuat dari JMockit adalah ekspresifnya. Untuk membuat tiruan dan menentukan perilakunya, alih-alih memanggil metode dari API tiruan, Anda hanya perlu mendefinisikannya secara langsung.

Artinya, Anda tidak akan melakukan hal-hal seperti:

API.expect(mockInstance.method()).andThenReturn(value).times(2);

Sebaliknya, harapkan hal-hal seperti:

new Expectation() { mockInstance.method(); result = value; times = 2; }

Tampaknya ini adalah lebih banyak kode, tetapi Anda dapat dengan mudah meletakkan ketiga baris hanya pada satu. Bagian yang sangat penting adalah Anda tidak akan berakhir dengan "rangkaian" panggilan metode yang dirantai. Alih-alih, Anda berakhir dengan definisi tentang bagaimana Anda ingin tiruan berperilaku saat dipanggil.

Jika Anda memperhitungkan bahwa pada bagian result = value Anda dapat mengembalikan apa pun (nilai tetap, nilai yang dihasilkan secara dinamis, pengecualian, dll), ekspresi JMockit menjadi lebih jelas.

2.4. Model Rekam-Replay-Verifikasi

Pengujian menggunakan JMockit dibagi menjadi tiga tahap yang dibedakan: rekam, putar ulang, dan verifikasi.

  1. Pada fase pencatatan , selama persiapan tes dan sebelum pemanggilan ke metode yang ingin kami jalankan, kami akan menentukan perilaku yang diharapkan untuk semua tes yang akan digunakan selama tahap berikutnya.
  2. The ulangan fase adalah satu di mana kode yang diuji dijalankan. Pemanggilan metode / konstruktor tiruan yang sebelumnya direkam pada tahap sebelumnya sekarang akan diputar ulang.
  3. Terakhir, pada fase verifikasi , kami akan menegaskan bahwa hasil tes adalah yang kami harapkan (dan bahwa tiruan berperilaku dan digunakan sesuai dengan apa yang ditentukan dalam fase rekaman).

Dengan contoh kode, wireframe untuk pengujian akan terlihat seperti ini:

@Test public void testWireframe() { // preparation code not specific to JMockit, if any new Expectations() {{ // define expected behaviour for mocks }}; // execute code-under-test new Verifications() {{ // verify mocks }}; // assertions }

3. Membuat Mock

3.1. Anotasi JMockit

Saat menggunakan JMockit, cara termudah untuk menggunakan tiruan, adalah menggunakan anotasi. Ada tiga untuk membuat tiruan ( @Mocked , @Injectable dan @Capturing ) dan satu untuk menentukan kelas yang sedang diuji ( @Tested ).

Saat menggunakan anotasi @Mocked di bidang, itu akan membuat contoh tiruan dari setiap objek baru dari kelas tertentu itu.

Di sisi lain, dengan anotasi @Injectable , hanya satu contoh tiruan yang akan dibuat.

Anotasi terakhir, @Capturing akan berperilaku seperti @Mocked, tetapi akan memperluas jangkauannya ke setiap subclass yang memperluas atau mengimplementasikan jenis kolom yang dianotasi.

3.2. Meneruskan Argumen ke Tes

Saat menggunakan JMockit dimungkinkan untuk melewatkan tiruan sebagai parameter uji. Ini sangat berguna untuk membuat tiruan hanya untuk satu pengujian itu secara khusus, seperti beberapa objek model kompleks yang memerlukan perilaku khusus hanya untuk satu pengujian misalnya. Ini akan menjadi seperti ini:

@RunWith(JMockit.class) public class TestPassingArguments { @Injectable private Foo mockForEveryTest; @Tested private Bar bar; @Test public void testExample(@Mocked Xyz mockForJustThisTest) { new Expectations() {{ mockForEveryTest.someMethod("foo"); mockForJustThisTest.someOtherMethod(); }}; bar.codeUnderTest(); } }

Cara membuat tiruan ini dengan meneruskannya sebagai parameter, alih-alih harus memanggil beberapa metode API, sekali lagi menunjukkan kepada kita ekspresi yang kita bicarakan sejak awal.

3.3. Contoh Lengkap

Untuk mengakhiri artikel ini, kami akan menyertakan contoh lengkap pengujian menggunakan JMockit.

Dalam contoh ini, kita akan menguji kelas Performer yang menggunakan Collaborator dalam metode perform () . Metode perform () ini, menerima objek Model sebagai parameter yang akan digunakannya getInfo () yang mengembalikan String, String ini akan diteruskan ke metode kolaborasi () dari Collaborator yang akan mengembalikan nilai true untuk pengujian khusus ini, dan nilai ini akan diteruskan ke metode accept () dari Collaborator .

Jadi, kelas yang diuji akan terlihat seperti ini:

public class Model { public String getInfo(){ return "info"; } } public class Collaborator { public boolean collaborate(String string){ return false; } public void receive(boolean bool){ // NOOP } } public class Performer { private Collaborator collaborator; public void perform(Model model) { boolean value = collaborator.collaborate(model.getInfo()); collaborator.receive(value); } }

Dan kode tesnya akan menjadi seperti ini:

@RunWith(JMockit.class) public class PerformerTest { @Injectable private Collaborator collaborator; @Tested private Performer performer; @Test public void testThePerformMethod(@Mocked Model model) { new Expectations() {{ model.getInfo();result = "bar"; collaborator.collaborate("bar"); result = true; }}; performer.perform(model); new Verifications() {{ collaborator.receive(true); }}; } }

4. Kesimpulan

Dengan ini, kami akan menyelesaikan pengantar praktis kami ke JMockit. Jika Anda ingin mempelajari lebih lanjut tentang JMockit, nantikan artikel selanjutnya.

Implementasi lengkap dari tutorial ini dapat ditemukan di proyek GitHub.

4.1. Artikel dalam Seri

Semua artikel dari seri:

  • JMockit 101
  • Panduan untuk JMockit - Harapan
  • Penggunaan Lanjutan JMockit