Con el uso de CDI, para la inyección de dependencias, y la consolidación de la plataforma Arquillian, ya no hay excusas en la plataforma Java EE para el desarrollo de pruebas.
5. Requisitos previos, conocer bien:
● Las técnicas de desarrollo / frameworks /
MADRID · NOV 21-22 · 2014
librerías que se estén utilizando
● Metodologías, conceptos y herramientas para
desarrollar pruebas: TDD/BDD, Mocks, Stubs,
Spies, Mockito, EasyMocks, etc.
6. MADRID · NOV 21-22 · 2014
Si, si… suena bien, pero...
Lo intenté y Java EE no me lo
puso fácil
Java developer
7. Evolución del desarrollo en Java EE
MADRID · NOV 21-22 · 2014
JNDI
CMP
EJB2
Struts
Hibernate Spring
JSF
JPA
EJB3
Seam CDI
Arquillian
Servicios de
contenedor
Modelo
POJO
Inyección de
dependencias
Integración
frameworks
Facilidad en
el desarrollo
Facilidad
para probar
Fuente: http://www.slideshare.net/nukeevry1/arquillian
8. Tipos de pruebas (automáticas)
MADRID · NOV 21-22 · 2014
● Pruebas unitarias
● Pruebas de integración
○ Infraestructura (contenedor / servidor de aplicaciones)
○ Con otros sistemas/aplicaciones
● Pruebas funcionales
9. MADRID · NOV 21-22 · 2014
Java EE 7
CDI
Extensions
Web
Fragments
Servlet 3.1
JSF 2.2
JSP 2.3
EL 3.0
JAX-WS 2.2
JAX-RS 2.0 JSON 1.0 WebSocket
1.0
CDI 1.1 Interceptors 1.0
JTA 1.2
Managed Beans 1.0
JPA 2.1 JMS 2.0
Common
Annotations 1.1 Concurrency 1.0
EJB 3.2
JCA 1.7 Batch 1.0
Bean Validations 1.1
¿MOCKS PARA TODO?
10. Arquitectura de pruebas en Java EE
MADRID · NOV 21-22 · 2014
Test Case
Arquillian
Core + Extensions
ShrinkWrap
Unit Testing Framework
Junit / TestNG
Coverage
JaCoCo
Maven
Container
TomEE Embedded
OpenWebBeans
Embedded Database
Derby
11. MADRID · NOV 21-22 · 2014
Arquillian: características
● Pruebas reales Java EE sin necesidad de mocks
● IDE friendly: ejecución de JUnit (o TestNG) desde el IDE o Maven
● Test enriquecidos: uso de características Java EE y extensiones
● Control del classpath: micro-despliegues en las pruebas
● Depuración de las pruebas desplegadas en servidor
● Contenedor agnóstico: múltiples adaptadores
12. Arquillian: configuración proyecto
● Incluir dependencias en fichero pom.xml
○ Importar arquillian core, extensiones y runtimes
○ Crear maven profiles para tener diferentes runtimes
● Configurar el fichero arquillian.xml para sobrescribir
MADRID · NOV 21-22 · 2014
valores por defecto (opcional)
13. Arquillian: desarrollo de pruebas
● Crear testcase con JUnit
● Incluir las clases bajo prueba usando ShrinkWrap
● Programar los métodos de pruebas @Test
● Ejecutar la prueba JUnit desde Maven / IDE
MADRID · NOV 21-22 · 2014
14. Arquillian: código ejemplo test
@RunWith(Arquillian.class)
public class GreeterTest {
MADRID · NOV 21-22 · 2014
@Inject
Greeter greeter;
@Deployment (name="GreeterTest")
public static JavaArchive createDeployment() {
return ShrinkWrap.create(JavaArchive.class)
.addClass(Greeter.class)
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
}
@Test
public void should_create_greeting() {
Assert.fail("Not yet implemented");
}
}
16. Arquillian: ¿cuantas clases meto?
.addPackages(true, Filters.exclude(".*Test.*|.*Mock.*"),"com.
project");
MADRID · NOV 21-22 · 2014
¿Todas? ¿Puedo?
● Tamaño JAR/WAR de pruebas
● Delimitar alcance de la pruebas
● Consideraciones rendimiento (p.e. contexto JPA)
● Si se usa embedded solo incluir clases aplicación
17. Arquillian: adaptadores runtimes
MADRID · NOV 21-22 · 2014
● Diferentes tipos:
○ Contenedor CDI (Weld, OpenWebBeans)
○ Contenedor EJB (OpenEJB 3.1)
○ Servidor de aplicaciones (Glassfish, JBoss, WAS, WebLogic,
TomEE, etc.)
● Diferentes formas de ejecución
○ Embedded
○ Managed
○ Remote
18. Arquillian: adaptadores runtimes
Runtime Tiempo total (seg.) Tiempo test (seg.)
glassfish-embedded 3.1.2.2 25 1,3
openwebbeans-embedded 1.1.6 5,8 0,03
jbossas-managed 7.1.1 20,4 0,3
wlp-managed 8.5.1.1 31,9 2,3
tomee-embedded 1.6.0 10,5 0,25
Resultados de ejecutar 10 veces una prueba de una inyección
de un EJB con @Inject.
MADRID · NOV 21-22 · 2014
19. Arquillian modos de ejecución
MADRID · NOV 21-22 · 2014
● Servidor
● Cliente (@RunAsClient).
○ Ejemplo: WS REST (Arquillian REST Extension)
○ Ambos modos son posibles a la vez
20. Context and Dependency Injection
MADRID · NOV 21-22 · 2014
● @Inject
● @Produce
● @Alternative, @Specializes
21. Creación de alternativas (deploy)
@Alternative
@Specializes
@Stereotype
@Retention(RUNTIME)
@Target(TYPE)
public @interface Mock {}
<beans>
MADRID · NOV 21-22 · 2014
<alternatives>
<stereotype>org.mycompany.testing.Mock</stereotype>
</alternatives>
</beans>
@Mock
public class MockLoginService extends LoginService { ...
}
22. Producción de alternativas (runtime)
MADRID · NOV 21-22 · 2014
@Mock @Produces
LoginService produceMockLoginService() {
LoginService login = mock(LoginService.class);
Mockito.when(login.validate(“user1”, “pass_invalid”)
.thenReturn(RESULT.FAIL);
Mockito.when(login.validate(“user1”, “pass_valid”)
.thenReturn(RESULT.SUCCESS);
return login;
}
23. Algunos ejemplos de mocks
● FacesContext ➜ valores en la request/session
● Servicios Web (JAX-WS / JAX-RS)
○ Unmarshal (XML/JSON ➜ POJO) con JAXB/Jackson
public static <T> getObjectFromXML(String xmlPath,
Class<T> className)
MADRID · NOV 21-22 · 2014
24. Arquillian Persistence Extension
MADRID · NOV 21-22 · 2014
● Gestión de transacciones
● Inserción de datos en base de datos
● Valida datos tras la prueba
● Se basa en DBUnit
25. Arquillian Persistence Extension
expected-users.yml
MADRID · NOV 21-22 · 2014
users.yml
useraccount:
- id: 1
firstname: John
lastname: Smith
username: doovde
password: password
- id: 2
firstname: Clark
lastname: Kent
username: superman
password: kryptonite
useraccount:
- firstname: John
lastname: Smith
username: doovde
password: password
- firstname: Clark
lastname: Kent
username: superman
password: LexLuthor
26. Arquillian Persistence Extension
@Test
@UsingDataSet("datasets/users.yml")
@ShouldMatchDataSet("datasets/expected-users.yml")
public void should_change_user_password() throws Exception
{
// given
String expectedPassword = "LexLuthor";
UserAccount user = em.find(UserAccount.class, 2L);
// when
user.setPassword(expectedPassword);
user = em.merge(user);
// then
assertEquals(expectedPassword, user.getPassword());
MADRID · NOV 21-22 · 2014
}
27. Estrategias de pruebas: End-to-End
MADRID · NOV 21-22 · 2014
Backing Bean
JPA
EJB
Arquillian
Persistence Derby
Port Mock
JAX-WS
Prueba
Arquillian
28. Estrategias de pruebas: Aisladas
Arquillian
Persistence Derby
JPA Mock EJB Mock
Backing Bean EJB JPA
MADRID · NOV 21-22 · 2014
Port Mock
JAX-WS
Prueba
Arquillian
Prueba
Arquillian
Prueba
Arquillian
32. Principales problemas encontrados
● Falta documentación de configuraciones avanzadas
● Diferentes versiones de Arquillian y extensions
● Diferente comportamiento según contenedores
MADRID · NOV 21-22 · 2014
33. Algunas lecciones aprendidas
● Utilizar pruebas aisladas para TDD
● Uso de plugin failsafe para pruebas end-to-end
● Uso de @Inject en vez de @EJB
● Probar bien la arquitectura base de pruebas
● Elaborar una metodología de uso para desarrolladores
● Integración continua: ¡Rompe el build! }:-)
MADRID · NOV 21-22 · 2014
34. MADRID · NOV 21-22 · 2014
FIN
@josemanlopez
https://www.linkedin.com/in/josemanlopez
http://josemlopez.blogspot.com.es/
http://goo.gl/MOi8zb
Hinweis der Redaktion
Misma vs diferente JVM de ejecución
TDD vs Entorno real
Profiles Maven
Filtros en plugin surfire / failsafe de Maven