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();
...
}
}