test example java junit installation order teardown

java - example - ¿En qué orden están Junit @ Before/@ After call?



junit libraries (6)

Creo que basándome en la documentación de @Before y @Before the right conclusion es dar a los métodos nombres únicos. Uso el siguiente patrón en mis pruebas:

public abstract class AbstractBaseTest { @Before public final void baseSetUp() { // or any other meaningful name System.out.println("AbstractBaseTest.setUp"); } @After public final void baseTearDown() { // or any other meaningful name System.out.println("AbstractBaseTest.tearDown"); } }

y

public class Test extends AbstractBaseTest { @Before public void setUp() { System.out.println("Test.setUp"); } @After public void tearDown() { System.out.println("Test.tearDown"); } @Test public void test1() throws Exception { System.out.println("test1"); } @Test public void test2() throws Exception { System.out.println("test2"); } }

dar como resultado

AbstractBaseTest.setUp Test.setUp test1 Test.tearDown AbstractBaseTest.tearDown AbstractBaseTest.setUp Test.setUp test2 Test.tearDown AbstractBaseTest.tearDown

Ventaja de este enfoque: los usuarios de la clase AbstractBaseTest no pueden anular los métodos setUp / tearDown por accidente. Si lo desean, necesitan saber el nombre exacto y pueden hacerlo.

(Menor) desventaja de este enfoque: los usuarios no pueden ver que hay cosas que suceden antes o después de su configuración / desvanecimiento. Necesitan saber que estas cosas son provistas por la clase abstracta. Pero supongo que esa es la razón por la que usan la clase abstracta

Tengo un paquete de prueba de integración. Tengo una clase IntegrationTestBase para extender todas mis pruebas. Esta clase base tiene un @Before ( public void setUp() ) y @After ( public void tearDown() ) para establecer conexiones API y DB. Lo que he estado haciendo es simplemente anular esos dos métodos en cada caso de prueba y llamar a super.setUp() y super.tearDown() . Sin embargo, esto puede causar problemas si alguien se olvida de llamar al súper o los coloca en el lugar equivocado y se lanza una excepción y se olvidan de llamar súper al final o algo así.

Lo que quiero hacer es tearDown métodos setUp y tearDown en la clase base y luego simplemente agregar nuestros propios @Before anotados @Before y @Before . Al hacer algunas pruebas iniciales, parece que siempre llama en este orden:

Base @Before Test @Before Test Test @After Base @After

pero estoy un poco preocupado de que la orden no esté garantizada y de que pueda causar problemas. Miré a mi alrededor y no había visto nada sobre el tema. ¿Alguien sabe si puedo hacer eso y no tengo ningún problema?

Código:

public class IntegrationTestBase { @Before public final void setUp() { *always called 1st?* } @After public final void tearDown() { *always called last?* } } public class MyTest extends IntegrationTestBase { @Before public final void before() { *always called 2nd?* } @Test public void test() { *always called 3rd?* } @After public final void after() { *always called 4th?* } }


Esta no es una respuesta a la pregunta del eslogan, pero es una respuesta a los problemas mencionados en el cuerpo de la pregunta. En lugar de utilizar @Before o @org.junit.Rule , busque usar @org.junit.Rule porque le da más flexibilidad. ExternalResource (a partir de 4.7) es la regla que más le interesará si está administrando conexiones. Además, si desea un orden de ejecución garantizado de sus reglas, use una RuleChain (a partir de la 4.10). Creo que todos estos estaban disponibles cuando se hizo esta pregunta. El siguiente ejemplo de código se copia de los javadocs de ExternalResource.

public static class UsesExternalResource { Server myServer= new Server(); @Rule public ExternalResource resource= new ExternalResource() { @Override protected void before() throws Throwable { myServer.connect(); }; @Override protected void after() { myServer.disconnect(); }; }; @Test public void testFoo() { new Client().run(myServer); } }


Puede usar la anotación @BeforeClass para asegurarse de que setup() siempre se llame primero. Del mismo modo, puede usar la anotación @AfterClass para asegurarse de que tearDown() siempre se llame último.

Esto generalmente no se recomienda, pero es supported .

No es exactamente lo que quiere, pero esencialmente mantendrá su conexión de base de datos abierta todo el tiempo en que se ejecutan las pruebas, y luego la cerrará de una vez por todas al final.


Sí, este comportamiento está garantizado:

@Before :

Los métodos @Before de las superclases se ejecutarán antes que los de la clase actual, a menos que se anulen en la clase actual. No se define ningún otro orden.

@After :

Los métodos @After declarados en superclases se ejecutarán después de los de la clase actual, a menos que se anulen en la clase actual.


Si cambia las cosas, puede declarar el resumen de la clase base y hacer que los descendientes declaren los métodos setUp y tearDown (sin anotaciones) a los que se llama en la clase base ''métodos anotados setUp y tearDown.


Un posible problema que me ha mordido antes:

Me gusta tener como máximo un método @Before en cada clase de prueba, porque el orden de ejecución de los métodos @Before definidos dentro de una clase no está garantizado. Normalmente, llamaré a dicho método setUpTest() .

Pero, aunque @Before está documentado como The @Before methods of superclasses will be run before those of the current class. No other ordering is defined. The @Before methods of superclasses will be run before those of the current class. No other ordering is defined. , esto solo se aplica si cada método marcado con @Before tiene un nombre único en la jerarquía de clases.

Por ejemplo, tuve lo siguiente:

public class AbstractFooTest { @Before public void setUpTest() { ... } } public void FooTest extends AbstractFooTest { @Before public void setUpTest() { ... } }

Esperaba que AbstractFooTest.setUpTest() ejecutara antes de FooTest.setUpTest() , pero solo se ejecutó FooTest.setupTest() . AbstractFooTest.setUpTest() no se llamó en absoluto.

El código se debe modificar de la siguiente manera para que funcione:

public void FooTest extends AbstractFooTest { @Before public void setUpTest() { super.setUpTest(); ... } }