Introducción a las pruebas con Arquillian

1. Información general

Arquillian es un marco de pruebas de integración independiente de contenedores para Jakarta EE. El uso de Arquillian minimiza la carga de administrar contenedores, implementaciones, inicializaciones de marcos, etc.

Podemos centrarnos en escribir pruebas reales y no en iniciar el entorno de prueba.

2. Conceptos básicos

2.1. Archivos de implementación

Existe una manera fácil de probar nuestra aplicación cuando se ejecuta dentro de un contenedor.

En primer lugar, la clase ShrinkWrap proporciona una API para crear archivos desplegables * .jar, * .war y * .ear .

Luego, Arquillian nos permite configurar la implementación de prueba usando la anotación @Deployment , en un método que devuelve un objeto ShrinkWrap .

2.2. Contenedores

Arquillian distingue tres tipos diferentes de contenedores:

  • Remoto: probado con un protocolo remoto como JMX
  • Administrado: contenedores remotos, pero su ciclo de vida lo administra Arquillian
  • Integrado: contenedores locales donde las pruebas se realizan utilizando protocolos locales

Además, podemos clasificar los contenedores por sus capacidades:

  • Aplicaciones de Jakarta EE implementadas en un servidor de aplicaciones como Glassfish o JBoss
  • Contenedores de servlet implementados en Tomcat o Jetty
  • Contenedores independientes
  • Contenedores OSGI

Examina la ruta de clases en tiempo de ejecución y selecciona automáticamente el contenedor disponible.

2.3. Enriquecimiento de prueba

Arquillian enriquece las pruebas proporcionando, por ejemplo, la inyección de dependencia para que podamos escribir nuestras pruebas fácilmente.

Podemos inyectar dependencias usando @Inject , inyectar recursos con @Resource , beans de sesión EJB usando @EJB, etc.

2.4. Varias pruebas de ejecución

Podemos crear múltiples implementaciones usando la anotación:

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

Donde el nombre es el nombre del archivo de implementación y el parámetro de orden es el orden de ejecución de la implementación, por lo que ahora podemos ejecutar pruebas en múltiples implementaciones al mismo tiempo usando la anotación:

@Test @OperateOnDeployment("myname")

La prueba anterior se ejecuta en el contenedor de implementación myname utilizando el orden definido en la anotación @Deployment .

2.5. Extensiones Arquillian

Arquillian ofrece múltiples extensiones en caso de que nuestras necesidades de prueba no estén cubiertas por el tiempo de ejecución del núcleo. Contamos con persistencia, transacciones, cliente / servidor, extensiones REST, etc.

Podemos habilitar esas extensiones agregando las dependencias adecuadas a los archivos de configuración de Maven o Gradle.

Las extensiones más utilizadas son Drone, Graphene y Selenium.

3. Dependencias y configuración de Maven

Agreguemos la siguiente dependencia a nuestro archivo pom.xml :

 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 

La última versión de las dependencias se puede encontrar aquí: arquillian-bom, org.glassfish.main.extras, org.jboss.arquillian.container.

4. Prueba simple

4.1. Crear un componente

Comencemos con un componente simple. No incluimos aquí ninguna lógica avanzada para poder centrarnos en las pruebas:

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

Usando Arquillian, queremos probar que esta clase se comporta correctamente cuando se invoca como un bean CDI.

4.2. Escribe nuestra primera prueba de Arquillian

Primero, debemos especificar que nuestra clase de prueba debe ejecutarse utilizando el corredor específico del marco:

@RunWith(Arquillian.class) 

Si vamos a ejecutar nuestras pruebas dentro de un contenedor, necesitamos usar la anotación @Deployment .

Arquillian no usa la ruta de clases completa para aislar el archivo de prueba. En su lugar, utiliza la clase ShrinkWrap , que es una API de Java para crear archivos. Cuando creamos el archivo para probar, especificamos qué archivos incluir en la ruta de clases para usar la prueba. Durante la implementación, ShrinkWrap aísla solo las clases necesarias para la prueba.

Usando el método addclass () podemos especificar todas las clases necesarias y también agregar un recurso de manifiesto vacío.

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()); }

En esta prueba, primero creamos cuatro instancias de automóvil y verificamos que el número de filas en la base de datos sea el mismo que creamos.

8. Conclusión

En este tutorial, nosotros:

  • introdujo los conceptos básicos de Arquillian
  • inyectado un componente en la prueba de Arquillian
  • probado un EJB
  • persistencia probada
  • realizó la prueba de Arquillian usando Maven

Puede encontrar el código del artículo en Github.