2008-12-08 17 views
23

Quiero hacer algunas pruebas funcionales en un servicio web (reparador). El banco de pruebas contiene un montón de casos de prueba, cada uno de los cuales realiza un par de peticiones HTTP en el servicio web.JUnit 4: Configurar las cosas en un banco de pruebas antes de las pruebas se ejecutan (como método @BeforeClass de una prueba, sólo por un conjunto de pruebas)

Naturalmente, el servicio web tiene que correr o las pruebas fallará. :-)

Iniciar el servicio web lleva un par de minutos (hace una gran carga de datos), por lo que quiero iniciarlo con la menor frecuencia posible (al menos todos los casos de prueba que solo GET recursos del servicio podrían compartir uno))

Entonces, ¿hay alguna manera de configurarme en la bomba en un banco de pruebas, antes de que las pruebas se ejecuten como en un método @BeforeClass de un caso de prueba?

Respuesta

1

jUnit no puede hacer ese tipo de cosas, aunque TestNG tiene anotaciones @BeforeSuite y @AfterSuite. Normalmente, obtienes tu sistema de compilación para hacerlo. En maven, existen las fases de "prueba previa a la integración" y "prueba posterior a la integración". En ANT, bueno, solo agrega los pasos a la tarea.

Su pregunta es más o menos un DUP de Before and After Suite execution hook in jUnit 4.x, así que me gustaría echar un vistazo a las sugerencias de allí.

+0

¿Por qué no BeforeSuite y AfterSuite trabajar? – guerda

-3

Como acotación al margen, que es una mala idea tener pruebas unitarias en realidad llamando recursos externos como servicios web, bases de datos, etc.

Las pruebas unitarias deben ser súper rápido para correr y un retraso de 'un par de minutos para cada ejecución de la suite significará que no se ejecutará tanto como debería.

Mi consejo:

mirada a burlarse de dependencias externas en las pruebas unitarias con algo como EasyMock (http://www.easymock.org/).

Cree un conjunto separado de pruebas de integración con algo como Fitnesse (http://fitnesse.org/) o una solución de fabricación casera que se ejecute en un entorno de prueba y que esté continuamente activo.

+0

hola, las pruebas de mi unidad no hacen ese tipo de cosas y son súper rápidas. estaba hablando de pruebas funcionales :-) –

0

Una opción es usar algo como Apache Ant para poner en marcha su banco de pruebas unidad. A continuación, puede poner una invocación objetivo antes y después de su objetivo junit para iniciar y detener el servicio web:

<target name="start.webservice"><!-- starts the webservice... --></target> 
<target name="stop.webservice"><!-- stops the webservice... --></target> 
<target name="unit.test"><!-- just runs the tests... --></target> 

<target name="run.test.suite" 
     depends="start.webservice, unit.test, stop.webservice"/> 

A continuación, ejecute su suite uso de la hormiga (o su herramienta de integración de la elección). La mayoría de los IDE tienen soporte Ant, y hace que sea mucho más fácil mover sus pruebas a un entorno de integración continua (muchas de las cuales usan objetivos Ant para definir sus propias pruebas).

21

La respuesta es ahora para crear una @ClassRule dentro de su suite. La regla se invocará antes o después (según cómo lo implemente) cada clase de prueba se ejecuta. Hay algunas clases básicas diferentes que puede ampliar/implementar. Lo bueno de las reglas de clase es que si no las implementa como clases anónimas, ¡puede reutilizar el código!

He aquí un artículo sobre ellos: http://java.dzone.com/articles/junit-49-class-and-suite-level-rules

Aquí hay un código de ejemplo para ilustrar su uso. Sí, es trivial, pero debe ilustrar el ciclo de vida lo suficientemente bien como para que pueda comenzar.

En primer lugar la definición suite:

import org.junit.*; 
import org.junit.rules.ExternalResource; 
import org.junit.runners.Suite; 
import org.junit.runner.RunWith; 


@RunWith(Suite.class) 
@Suite.SuiteClasses({ 
    RuleTest.class, 
}) 
public class RuleSuite{ 

    private static int bCount = 0; 
    private static int aCount = 0; 

    @ClassRule 
    public static ExternalResource testRule = new ExternalResource(){ 
      @Override 
      protected void before() throws Throwable{ 
       System.err.println("before test class: " + ++bCount); 
       sss = "asdf"; 
      }; 

      @Override 
      protected void after(){ 
       System.err.println("after test class: " + ++aCount); 
      }; 
     }; 


    public static String sss; 
} 

Y ahora la definición de clase de prueba:

import static org.junit.Assert.*; 

import org.junit.ClassRule; 
import org.junit.Rule; 
import org.junit.Test; 
import org.junit.rules.ExternalResource; 

public class RuleTest { 

    @Test 
    public void asdf1(){ 
     assertNotNull("A value should've been set by a rule.", RuleSuite.sss); 
    } 

    @Test 
    public void asdf2(){ 
     assertEquals("This value should be set by the rule.", "asdf", RuleSuite.sss); 
    } 
} 
+0

"La regla se invocará antes o después (dependiendo de cómo lo implemente) cada clase de prueba se ejecuta" - No puedo confirmar eso. El método de evaluación() de mi ClassRule solo se ha llamado una vez, aunque agregué dos clases de prueba al paquete. –

+0

De hecho, la regla se invocará antes o después de ejecutar la clase de prueba dependiendo de cierta implementación. En el ejemplo provisto por ** @ ArtB **, la regla implementada a nivel de suite. Por lo tanto, se llamará una vez antes de que se ejecuten todas las pruebas en el conjunto y una vez después de que se ejecuten todas las pruebas en el conjunto. Entonces, la respuesta de ** @ ArtB ** funciona bien. – flaz14

Cuestiones relacionadas