2012-04-19 20 views
7

Estamos pasando de usar TestNG con un JBoss incrustado a usar Arquillian con un servidor remoto.anotaciones @BeforeClass que invocan métodos dos veces cuando se usa Arquillian en el servidor remoto

Estamos ejecutando una prueba simple que tiene un método anotado con @BeforeClass que realiza alguna configuración de prueba. Después de una gran cantidad de búsquedas, parece que el método de configuración se llama dos veces: una vez en la consola donde estamos ejecutando nuestro comando Maven para ejecutar la prueba y otra vez cuando la guerra de prueba se implementa en nuestro servidor remoto y se ejecuta la prueba. Estos son dos JVMS separados: uno que se ejecuta fuera del contenedor y otro que se ejecuta dentro del contenedor. Mi preferencia es simplemente ejecutar la última.

¿Es este el comportamiento que debería esperar o hay algo que me puede estar perdiendo?

Por ahora, en realidad estamos verificando si estamos en el contenedor o no y, de ser así, ejecutamos nuestro código de configuración. Esto funciona, pero me gustaría saber si hay una mejor manera.

Algunos fragmentos de nuestro código (ignore la simplicidad del código y el hecho de que el método setupComponents realmente no es necesario aquí, hay pruebas mucho más complicadas que estamos migrando que necesitarán esta funcionalidad):

public class BaseTest extends Arquillian 
{ 
    private static Log log = LogFactory.getLog(SeamTest.class); 

    @Deployment 
    public static Archive<?> createDeployment() 
    { 
     // snip... basically, we create a test war here 
    } 

    /** 
    * todo - there might be a better way to do this 
    */ 
    private boolean runningInContainer() 
    { 
     try 
     { 
      new InitialContext().lookup("java:comp/env"); 
      return true; 
     } 
     catch (NamingException ex) 
     { 
      return false; 
     } 
    } 

    @BeforeClass 
    public void setupOnce() throws Exception 
    { 
     getLog().debug("in setupOnce(): " + runningInContainer()); 
     if (runningInContainer()) 
     { 
      new ComponentTest() 
      { 
       protected void testComponents() throws Exception 
       { 
        setupComponents(); 
       } 
      }.run(); 
     } 
    } 

    public User createUser() 
    { 
     // ... 
    } 

    public Log getLog() 
    { 
     // snip... 
    } 

    public UserDao getUserDao() 
    { 
     // ... 
    } 

    public abstract class ComponentTest 
    { 
     protected abstract void testComponents() throws Exception; 

     public void run() throws Exception 
     { 
      try { 
       testComponents(); 
      } finally { 

      } 
     } 
    } 

} 

public class UserDaoTest extends BaseTest 
{ 
    UserDao userDao; 

    @Override 
    protected void setupComponents() 
    { 
     getLog().debug("in setupComponents: " + runningInContainer()); 
     userDao = getUserDao(); 
    } 

    @Test 
    public void testGetUser() throws Exception 
    { 
     getLog().debug("in testGetUser: " + runningInContainer()); 

     new ComponentTest() 
     { 
      protected void testComponents() throws Exception 
      { 
       User user0 = createUser(); 
       user0.setName("frank"); 

       userDao.merge(user0); 

       User retrievedUser = userDao.findByName("frank"); 
       assertNotNull(retrievedUser); 
      } 

     }.run(); 
    } 

} 

esto básicamente me da salida que se parece a esto:

Desde la consola donde se ejecuta mvn:

in setupOnce(): false 

Desde el servidor jboss:

in setupOnce(): true 
in setupComponents: true 
in testGetUser: true 
+0

A partir de ahora, '@ BeforeClass' está pensado para funcionar sólo en el cliente para las pruebas Arquillian. Pero esto parece un error. ¿Podría actualizar esta pregunta con su código? Nota: [ARQ-351] (https://issues.jboss.org/browse/ARQ-351) traerá el control para la ejecución de los eventos del ciclo de vida. –

+0

@VineetReynolds, el código es muy simple. Publicaré un fragmento. Si el comportamiento esperado en el futuro es tener solo "@BeforeClass" fuera del contenedor, ¿cómo puedo anotar un método que hará que se ejecute en el contenedor pero antes de todas las pruebas de esa clase? –

+0

Además, @VineetReynolds, si desea publicar una respuesta en lugar de su comentario e incluir una solución alternativa para que pueda obtener crédito, hágalo. –

Respuesta

5

Esto es un comportamiento "esperado". No es realmente agradable, pero así es como funciona Arqullian.

JUnit

  • @BeforeClass/@AfterClass sólo se ejecutan en ClientSide
  • El estado de la clase de prueba se pierde entre @test, en un recipiente todo el ciclo de vida se repite para cada prueba
  • @Before/@After se ejecutan en función de la RunMode (cliente/servidor)

TestNG

  • todo lo que se ejecuta tanto en el servidor y el cliente
+0

Después de la publicación, esta es básicamente la respuesta que recibí del equipo Arquillian.Hay algunos problemas Arquillian abiertos (en este punto) que cubren esto: https://issues.jboss.org/browse/ARQ-567 https://issues.jboss.org/browse/ARQ-197 –

Cuestiones relacionadas