JMockit 101

1. Pengenalan

Dengan artikel ini, kita akan memulakan siri baru yang berpusat di sekitar alat mengejek JMockit.

Dalam ansuran pertama ini kita akan membincangkan mengenai JMockit, ciri-cirinya dan bagaimana ejekan dibuat dan digunakan dengannya.

Artikel kemudian akan menumpukan pada dan mendalami kemampuannya.

2. JMockit

2.1. Pengenalan

Pertama sekali, mari kita bincangkan apa itu JMockit: kerangka Java untuk mengejek objek dalam ujian (anda boleh menggunakannya untuk kedua-dua JUnit dan TestNG).

Ia menggunakan API instrumentasi Java untuk memodifikasi bytecode kelas semasa waktu berjalan untuk mengubah tingkah laku mereka secara dinamis. Beberapa kelebihannya adalah kebolehlihatannya dan kemampuannya yang luar biasa untuk mengejek kaedah statik dan peribadi.

Mungkin anda baru menggunakan JMockit, tetapi ia pasti bukan kerana ia baru. Pengembangan JMockit dimulakan pada bulan Jun 2006 dan pelepasan pertama yang stabil bermula pada bulan Disember 2012, jadi sudah lama berlalu (versi sekarang adalah 1.24 pada saat menulis artikel)

2.2. Ketergantungan Maven

Pertama, kita perlu menambahkan kebergantungan jmockit ke projek kita:

 org.jmockit jmockit 1.41 

2.3. Ketokohan JMockit

Seperti yang diberitahu sebelumnya, salah satu titik terkuat dari JMockit adalah keterbukaannya. Untuk membuat ejekan dan menentukan tingkah laku mereka, bukannya memanggil kaedah dari API mengejek, anda hanya perlu menentukannya secara langsung.

Ini bermaksud bahawa anda tidak akan melakukan perkara seperti:

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

Sebaliknya, harapkan perkara seperti:

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

Nampaknya ia lebih banyak kod, tetapi anda boleh meletakkan ketiga baris hanya pada satu. Bahagian yang sangat penting adalah anda tidak akan berakhir dengan "kereta api" panggilan kaedah yang dirantai. Sebagai gantinya, anda berakhir dengan definisi bagaimana anda mahu ejekan berperilaku ketika dipanggil.

Sekiranya anda mengambil kira bahawa pada bahagian hasil = nilai anda boleh mengembalikan apa-apa (nilai tetap, nilai yang dihasilkan secara dinamik, pengecualian, dan lain-lain), ekspresi JMockit menjadi lebih jelas.

2.4. Model Rekod-Main Ulang-Verifikasi

Ujian menggunakan JMockit dibahagikan kepada tiga peringkat yang dibezakan: rakam, mainkan semula dan sahkan.

  1. Pada fasa rekod , semasa persiapan ujian dan sebelum pemanggilan kaedah yang ingin kami laksanakan, kami akan menentukan tingkah laku yang diharapkan untuk semua ujian yang akan digunakan pada tahap berikutnya.
  2. The ulangan fasa adalah salah satu di mana kod di bawah ujian dilaksanakan. Doa kaedah / konstruktor olok-olok yang sebelumnya direkodkan pada tahap sebelumnya kini akan diulang.
  3. Terakhir, pada fasa verifikasi , kami akan menegaskan bahawa hasil ujian adalah yang kami harapkan (dan ejekan itu berlaku dan digunakan sesuai dengan apa yang ditentukan dalam fasa rakaman).

Dengan contoh kod, bingkai kawat untuk ujian akan kelihatan 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 ejekan

3.1. Anotasi JMockit

Semasa menggunakan JMockit, cara termudah untuk menggunakan ejekan, adalah dengan menggunakan anotasi. Terdapat tiga untuk membuat ejekan ( @Mocked , @Injectable dan @Capturing ) dan satu untuk menentukan kelas yang sedang diuji ( @ Diuji ).

Semasa menggunakan anotasi @Mocked di lapangan, ia akan membuat contoh ejekan dari setiap objek baru kelas tertentu.

Sebaliknya, dengan anotasi @Injectable , hanya satu contoh tiruan yang akan dibuat.

Anotasi terakhir, @Capturing akan berkelakuan seperti @Mocked, tetapi akan memperluas jangkauannya ke setiap subkelas yang memperluas atau melaksanakan jenis medan yang diberi penjelasan.

3.2. Menyampaikan Hujah ke Ujian

Semasa menggunakan JMockit adalah mungkin untuk mengolok-olokkan ejekan sebagai parameter ujian. Ini cukup berguna untuk membuat tiruan hanya untuk satu ujian itu, seperti beberapa objek model kompleks yang memerlukan tingkah laku khusus hanya untuk satu ujian misalnya. Ia 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, dan bukannya perlu memanggil beberapa kaedah API, sekali lagi menunjukkan kepada kita kebolehpresi yang kita bicarakan sejak awal.

3.3. Contoh Lengkap

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

Dalam contoh ini, kami akan menguji kelas Performer yang menggunakan Collaborator dalam kaedah perform () . Ini melaksanakan () kaedah, menerima Model objek sebagai parameter yang ia akan menggunakan yang getInfo () pulangan yang String, String ini akan diserahkan kepada Bekerjasama () kaedah dari Rakan usaha sama yang akan kembali benar untuk ujian ini khususnya, dan nilai ini akan diteruskan ke kaedah menerima () dari Kolaborator .

Jadi, kelas yang diuji akan kelihatan 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 kod ujian akan menjadi seperti:

@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 melengkapkan pengenalan praktikal kami ke JMockit. Sekiranya anda ingin mengetahui lebih lanjut mengenai JMockit, nantikan artikel yang akan datang.

Pelaksanaan penuh tutorial ini boleh didapati di projek GitHub.

4.1. Artikel dalam Siri

Semua artikel siri ini:

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