Pengantar Pengujian dengan Arquillian

1. Ikhtisar

Arquillian adalah framework pengujian integrasi container-agnostik untuk Jakarta EE. Menggunakan Arquillian meminimalkan beban pengelolaan kontainer, penerapan, inisialisasi kerangka kerja, dan sebagainya.

Kita dapat fokus pada penulisan pengujian yang sebenarnya dan bukan pada bootstrap lingkungan pengujian.

2. Konsep Inti

2.1. Arsip Penerapan

Ada cara mudah untuk menguji aplikasi kita saat dijalankan di dalam container.

Pertama, kelas ShrinkWrap menyediakan API untuk membuat file * .jar, * .war, dan * .ear yang dapat diterapkan .

Kemudian, Arquillian memungkinkan kita mengonfigurasi penerapan uji coba menggunakan anotasi @Deployment - pada metode yang mengembalikan objek ShrinkWrap .

2.2. Wadah

Arquillian membedakan tiga jenis wadah:

  • Diuji dari jarak jauh menggunakan protokol jarak jauh seperti JMX
  • Dikelola - kontainer jarak jauh tetapi siklus hidupnya dikelola oleh Arquillian
  • Tertanam - wadah lokal tempat pengujian dilakukan menggunakan protokol lokal

Selain itu, kami dapat mengklasifikasikan kontainer berdasarkan kemampuannya:

  • Aplikasi Jakarta EE diterapkan pada server aplikasi seperti Glassfish atau JBoss
  • Kontainer servlet digunakan di Tomcat atau Jetty
  • Wadah mandiri
  • Wadah OSGI

Ini memeriksa classpath waktu proses dan secara otomatis memilih container yang tersedia.

2.3. Uji Pengayaan

Arquillian memperkaya pengujian dengan menyediakan, misalnya injeksi ketergantungan, sehingga kita dapat menulis pengujian dengan mudah.

Kita bisa memasukkan dependensi menggunakan @Inject , menginjeksi resource dengan @Resource , kacang sesi EJB menggunakan @EJB, dll.

2.4. Beberapa Pelari Tes

Kita dapat membuat banyak penerapan menggunakan anotasi:

@Deployment(name="myname" order = 1)

Di mana namanya adalah nama file penerapan dan parameter urutannya adalah urutan eksekusi penerapan, jadi sekarang kita dapat menjalankan pengujian pada penerapan berganda secara bersamaan menggunakan anotasi:

@Test @OperateOnDeployment("myname")

Tes before dijalankan pada wadah penerapan myname menggunakan urutan yang ditentukan dalam anotasi @Deployment .

2.5. Ekstensi Arquillian

Arquillian menawarkan beberapa ekstensi jika kebutuhan pengujian kami tidak tercakup oleh runtime inti. Kami memiliki persistensi, transaksi, klien / server, ekstensi REST, dll.

Kita bisa mengaktifkan ekstensi tersebut dengan menambahkan dependensi yang sesuai ke file konfigurasi Maven atau Gradle.

Ekstensi yang biasa digunakan adalah Drone, Graphene, dan Selenium.

3. Ketergantungan dan Penyiapan Maven

Mari tambahkan ketergantungan berikut ke file pom.xml kita :

 org.jboss.arquillian arquillian-bom 1.1.13.Final import pom   org.glassfish.main.extras glassfish-embedded-all 4.1.2 test   org.jboss.arquillian.container arquillian-glassfish-embedded-3.1 1.0.0.Final test 

Versi terbaru dari dependensi dapat ditemukan di sini: arquillian-bom, org.glassfish.main.extras, org.jboss.arquillian.container.

4. Tes Sederhana

4.1. Buat Komponen

Mari kita mulai dengan komponen sederhana. Kami tidak menyertakan logika lanjutan apa pun di sini untuk dapat fokus pada pengujian:

public class Component { public void sendMessage(PrintStream to, String msg) { to.println(message(msg)); } public String message(String msg) { return "Message, " + msg; } }

Menggunakan Arquillian, kami ingin menguji bahwa kelas ini berperilaku dengan benar saat dipanggil sebagai kacang CDI.

4.2. Tulis Tes Arquillian Pertama Kami

Pertama, kita perlu menentukan bahwa kelas pengujian kita harus dijalankan menggunakan runner khusus framework:

@RunWith(Arquillian.class) 

If we're going to run our tests inside a container, we need to use the @Deployment annotation.

Arquillian does not use the entire classpath to isolate the test archive. Instead, it uses the ShrinkWrap class, that is a Java API for creating archives. When we create the archive to test, we specify what files to include in the classpath to use the test. During the deployment, ShrinkWrap isolates only the classes needed for the test.

Using the addclass() method we can specify all necessary classes, and also add an empty manifest resource.

The JavaArchive.class creates a mockup web archive called test.war, this file is deployed into the container and then is used by Arquillian to perform tests:

@Deployment public static JavaArchive createDeployment() { return ShrinkWrap.create(JavaArchive.class) .addClass(Component.class) .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"); }

Then we inject our component in the test:

@Inject private Component component;

Finally, we perform our test:

assertEquals("Message, MESSAGE",component.message(("MESSAGE"))); component.sendMessage(System.out, "MESSAGE");

5. Testing Enterprise Java Beans

5.1. Enterprise Java Bean

With Arquillian we can test dependency injection of an Enterprise Java Bean, to do that we create a class that has a method for converting any word to lowercase:

public class ConvertToLowerCase { public String convert(String word){ return word.toLowerCase(); } }

Using this class, we create a stateless class for calling the method created before:

@Stateless public class CapsConvertor { public ConvertToLowerCase getLowerCase(){ return new ConvertToLowerCase(); } }

The CapsConvertor class gets injected into a service bean:

@Stateless public class CapsService { @Inject private CapsConvertor capsConvertor; public String getConvertedCaps(final String word){ return capsConvertor.getLowerCase().convert(word); } }

5.2. Test the Enterprise Java Bean

Now we can use Arquillian to test our enterprise Java Bean, injecting the CapsService:

@Inject private CapsService capsService; @Test public void givenWord_WhenUppercase_ThenLowercase(){ assertTrue("capitalize".equals(capsService.getConvertedCaps("CAPITALIZE"))); assertEquals("capitalize", capsService.getConvertedCaps("CAPITALIZE")); }

Using ShrinkWrap, we ensure that all classes are wired correctly:

@Deployment public static JavaArchive createDeployment() { return ShrinkWrap.create(JavaArchive.class) .addClasses(CapsService.class, CapsConvertor.class, ConvertToLowerCase.class) .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"); }

6. Testing JPA

6.1. Persistence

We can also use Arquillian to test persistence. First, we are going to create our entity:

@Entity public class Car { @Id @GeneratedValue private Long id; @NotNull private String name; // getters and setters }

We have a table that holds names of cars.

Then we are going to create our EJB to perform basic operations on our data:

@Stateless public class CarEJB { @PersistenceContext(unitName = "defaultPersistenceUnit") private EntityManager em; public Car saveCar(Car car) { em.persist(car); return car; } public List findAllCars() { Query query = em.createQuery("SELECT b FROM Car b ORDER BY b.name ASC"); List entries = query.getResultList(); return entries == null ? new ArrayList() : entries; public void deleteCar(Car car) { car = em.merge(car); em.remove(car); } }

With saveCar we can save the car names into the database, we can get all cars stored with findAllCars, and also we can delete a car from the database with deleteCar.

6.2. Test Persistence With Arquillian

Now we can perform some basic tests using Arquillian.

First, we add our classes to our ShrinkWrap:

.addClasses(Car.class, CarEJB.class) .addAsResource("META-INF/persistence.xml")

Then we create our test:

@Test public void testCars() { assertTrue(carEJB.findAllCars().isEmpty()); Car c1 = new Car(); c1.setName("Impala"); Car c2 = new Car(); c2.setName("Lincoln"); carEJB.saveCar(c1); carEJB.saveCar(c2); assertEquals(2, carEJB.findAllCars().size()); carEJB.deleteCar(c1); assertEquals(1, carEJB.findAllCars().size()); }

Dalam pengujian ini, pertama-tama kami membuat empat instance mobil, dan kami memeriksa bahwa jumlah baris dalam database sama dengan yang kami buat.

8. Kesimpulan

Dalam tutorial ini, kami:

  • memperkenalkan konsep inti Arquillian
  • menyuntikkan komponen ke dalam tes Arquillian
  • menguji EJB
  • ketekunan yang teruji
  • melakukan tes Arquillian menggunakan Maven

Anda dapat menemukan kode dari artikel di atas di Github.