2011-02-28 24 views
14

¿Es posible utilizar algún tipo de marco de burla con Arquillian, o precisamente cómo burlarse de los EJB inyectados? Sé que, con el uso de CDI (Contexts and Dependency Injection), es posible inyectar alternativas en la prueba. Pero sin CDI como mecanismo de inyección, cuando solo estoy usando inyección EJB, ¿cómo es posible?¿Cómo burlarse de los servicios con Arquillian?

recientemente he probado mis EJB con interfaz de servicio de aplicación simulada de la siguiente manera:

// Service inteface 
public interface Audit { 
    void audit(String info); 
} 

// Mock implementation 
@Stateless 
public class MockAuditBean implements Audit { 

    public static String lastInfo = null; 

    @Override 
    public void audit(String info) { 
     this.lastInfo = info; 
    } 
} 

// assert in test 
assertTrue(MockAuditBean.lastInfo.contains("dummy")); 

Este enfoque es posible, pero requiere una gran cantidad de implementaciones simuladas personalizado. Lo que es peor, las instancias inyectadas de simulacros son proxies y usan la interfaz de servicio. No se pueden convertir para simular clase de implementación para comparar resultados. Solo se pueden usar miembros estáticos y métodos de implementación simulada.

He probado también otras posibilidades para establecer los EJB relacionada manualmente. Este enfoque tiene varios inconvenientes. Requiere que el EJB objetivo de prueba tenga miembros o instaladores no privados para ellos. Cuando el EJB objetivo se basa en la anotación del ciclo de vida de @PostConstruct, debe llamarlo después de la configuración de "inyección" manual. La ventaja de esta solución es la capacidad de utilizar frameworks simulados, como mockito o jMock.

tener a alguien una experiencia para compartir, cómo probar y puesta en marcha de estas pruebas de integración, o incluso el uso de marcos de burla en ella?

Respuesta

2

IMO, los EJB no están diseñados teniendo en cuenta las pruebas. Tu alternativa parece un compromiso bastante bueno y yo iría por eso. Usar mockito es una ventaja importante y la uso incluso cuando trabajo con CDI.

que haría uso del ámbito miembro de "default" y javadoc a otros desarrolladores acceder a ellas sólo para pruebas.

0

Si realmente desea interactuar con los simulacros en sus pruebas de integración (por ejemplo, una de las razones podría ser que todavía no tiene una implementación completa o tiene una fachada para sistemas externos sobre los que no tiene control), hay una manera bastante fácil de integrar Mockito con sus pruebas Arquillian, eche un vistazo a this example from the showcase. En realidad, es extensión por sí mismo, pero no se ha lanzado como uno solo.

1

Este artículo de Oracle muestra un enfoque de "inyección" un EJB para probar usando JUnit y Mockito: http://www.oracle.com/technetwork/articles/java/unittesting-455385.html

Editar: Básicamente la inclusión de Mockito permite por burlarse objetos como EntityManager etc .:

import static org.mockito.Mockito.*; 

...

em = mock(EntityManager.class); 

Ellos muestran el enfoque de EJB también usando mockito. Teniendo en cuenta un EJB:

@Stateless 
public class MyResource { 
@Inject 
Instance<Consultant> company; 

@Inject 
Event<Result> eventListener; 

La prueba puede "inyectar" esos objetos:

public class MyResourceTest { 

private MyResource myr; 
@Before 
public void initializeDependencies(){ 
this.myr = new MyResource(); 
this.myr.company = mock(Instance.class); 
this.myr.eventListener = mock(Event.class); 
} 

Tenga en cuenta que myresource y myresource están en la misma ruta de clase, pero diferentes carpetas de origen por lo que sus pruebas tienen acceso a la zona protegida campos, company y eventListener.


Editar:

Nota: se puede usar FacesMockitoRunner de JBoss (https://community.jboss.org/thread/170800) para obtener este hecho para los componentes JSF comunes y utilizar las anotaciones para los demás (Java EE 6 con CDI habilitado como un pre requisito para esto, pero no requiere servidor JBoss):

  1. Incluir JSF, Mockito y dependencias JSF-Mockito en Maven:

    <dependency> 
         <groupId>junit</groupId> 
         <artifactId>junit</artifactId> 
         <version>4.11</version> 
         <scope>test</scope> 
        </dependency> 
        <dependency> 
         <groupId>org.mockito</groupId> 
         <artifactId>mockito-core</artifactId> 
         <version>1.9.5</version> 
         <scope>test</scope> 
        </dependency> 
        <dependency> 
         <groupId>org.jboss.test-jsf</groupId> 
         <artifactId>jsf-mockito</artifactId> 
         <version>1.1.7-SNAPSHOT</version> 
         <scope>test</scope> 
        </dependency> 
    
  2. Añadir la anotación @RunWith a su prueba:

    @RunWith(FacesMockitoRunner.class) 
    public class MyTest { 
    
  3. Inyectar caras comunes de objetos Uso de anotaciones:

    @Inject 
    FacesContext facesContext; 
    @Inject 
    ExternalContext ext; 
    @Inject 
    HttpServletRequest request; 
    
  4. Mock cualquier otro objeto utilizando las anotaciones @org.mockito.Mock (Parece FacesMockitoRunner llama a esto detrás de las escenas por lo que puede no ser necesario aquí):

    @Mock MyUserService userService; 
    @Mock MyFacesBroker broker; 
    @Mock MyUser user; 
    
  5. Init del Mocks inyectado utilizar la configuración

    @Before public void initMocks() { 
        // Init the mocks from above 
        MockitoAnnotations.initMocks(this); 
    } 
    
  6. su prueba como de costumbre:

    assertSame(FacesContext.getCurrentInstance(), facesContext); 
    when(ext.getSessionMap()).thenReturn(session); 
    assertSame(FacesContext.getCurrentInstance().getExternalContext(), ext); 
    assertSame(FacesContext.getCurrentInstance().getExternalContext().getSessionMap(), ext.getSessionMap()); 
    

etc.

+0

¿Podría al menos parafrasear parte del contenido del enlace? Los enlaces por sí solos están sujetos a la "podredumbre del enlace", y tal esfuerzo sería apreciado. – trudyscousin

1

Es posible que desee echar un vistazo a lo que testfun-JEE le permite realizar pruebas unitarias (no pruebas de integración) de sus EJB fuera de un contenedor. testfun-JEE se encarga de inyectar EJBs así como EntityManager y algunos recursos estándar directamente en su clase de prueba: las referencias dentro de estos EJB a otros EJB se resuelven automáticamente.

Y lo mejor es que puede burlarse de cualquier dependencia simplemente agregando una variable miembro a su prueba anotada con @Mock - testfun-JEE inyectará esta simulación donde sea necesario.

Ver ejemplos en https://github.com/michaelyaakoby/testfun.

Por cierto, si bien este marco fue publicado recientemente (como hoy ...) está siendo ampliamente utilizado durante más de un año en mi empresa.

0

Trabaja con un framework, como Mockito.

Desafortunadamente, Arquillian no incluye automáticamente las dependencias necesarias. Usted puede añadirlos en su función @Deployment:

@Deployment 
public static WebArchive deploy() 
{ 
    return ShrinkWrap.create(WebArchive.class) 
     .addAsLibraries(// add maven resolve artifacts to the deployment 
      DependencyResolvers.use(MavenDependencyResolver.class) 
      .artifact("org.mockito:mockito-all:1.8.3") 
      .resolveAs(GenericArchive.class)) 
     ); 
} 

source

Luego, en el método de @Test podría usar:

mock(MockedService.class).methodName() 

Esta muestra github muestra una manera de permitir la detección automática, la cual parece requerir alguna configuración: source