Tengo una suite de prueba de integración. Tengo una IntegrationTestBase
clase para extender todas mis pruebas. Esta clase base tiene un método @Before
( public void setUp()
) y @After
( public void tearDown()
) para establecer conexiones API y DB. Lo que he estado haciendo es anular esos dos métodos en cada caso de prueba y llamar super.setUp()
y super.tearDown()
. Sin embargo, esto puede causar problemas si alguien olvida llamar al súper o los coloca en el lugar equivocado y se produce una excepción y se olvida de llamar al súper finalmente o algo así.
Lo que quiero hacer es crear los métodos setUp
y tearDown
en la clase base final
y luego simplemente agregar nuestros propios métodos @Before
y anotados @After
. Al hacer algunas pruebas iniciales, parece que siempre se llama en este orden:
Base @Before
Test @Before
Test
Test @After
Base @After
pero me preocupa un poco que el pedido no esté garantizado y que pueda causar problemas. Miré a mi alrededor y no he 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?* }
}
fuente
MyTest
falta unextends
?Respuestas:
Sí, este comportamiento está garantizado:
@Before
:@After
:fuente
@Before
métodos no está garantizado. Si hay 10@Before
métodos, cada uno de ellos puede ejecutarse en cualquier orden; justo antes de cualquier otro método.@Before
y@After
antes de cualquier otro método de clase (una vez por método), o justo antes y después de todo el conjunto de métodos de clase (una vez por clase)?junit-4.12
.Una potencial trampa que me ha mordido antes:
Me gusta tener como máximo un
@Before
método en cada clase de prueba, porque el orden de ejecución de los@Before
métodos definidos dentro de una clase no está garantizado. Por lo general, llamaré a tal métodosetUpTest()
.Pero, aunque
@Before
está documentado comoThe @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:
Esperaba
AbstractFooTest.setUpTest()
correr antesFooTest.setUpTest()
, pero soloFooTest.setupTest()
fue ejecutado.AbstractFooTest.setUpTest()
no fue llamado en absoluto.El código debe modificarse de la siguiente manera para que funcione:
fuente
@Before
/@After
métodos en la clase basefinal
, por lo que el compilador se quejará si (accidentalmente) intenta anularlos en la subclase.@Before
métodos marcados se ignorarán si una subclase también tiene un@Before
método.Creo que basado en la documentación de la
@Before
y@After
la conclusión correcta es dar a los métodos nombres únicos. Utilizo el siguiente patrón en mis pruebas:y
dar como resultado
Ventaja de este enfoque: los usuarios de la clase AbstractBaseTest no pueden anular los métodos setUp / tearDown por accidente. Si quieren, necesitan saber el nombre exacto y pueden hacerlo.
Desventaja (menor) de este enfoque: los usuarios no pueden ver que están sucediendo cosas antes o después de su configuración / desgarro. Necesitan saber que estas cosas son proporcionadas por la clase abstracta. Pero supongo que esa es la razón por la que usan la clase abstracta
fuente
Si cambia las cosas, puede declarar su resumen de clase base y hacer que los descendientes declaren los métodos setUp y tearDown (sin anotaciones) que se llaman en los métodos setUp y tearDown anotados de la clase base.
fuente
Puede usar la
@BeforeClass
anotación para asegurarse de quesetup()
siempre se llame primero. Del mismo modo, puede usar la@AfterClass
anotación para asegurarse de quetearDown()
siempre se llame último.Esto generalmente no se recomienda, pero es compatible .
No es exactamente lo que desea, pero esencialmente mantendrá su conexión de base de datos abierta todo el tiempo que se ejecutan sus pruebas, y luego la cerrará de una vez por todas al final.
fuente
setupDB()
ycloseDB()
marcarlos con@BeforeClass
y@AfterClass
y reemplazar sus métodos antes / después consetup()
ytearDown()
@BeforeClass
y@AfterClass
deben ser estáticos. ¿Qué pasa con el caso, cuando queremos usar variables de instancia dentro de estos métodos?@BeforeClass
con Powermock: solo funciona para la primera ejecución de prueba. Vea este número: github.com/powermock/powermock/issues/398Esta no es una respuesta a la pregunta del lema, pero es una respuesta a los problemas mencionados en el cuerpo de la pregunta. En lugar de usar @Before o @After, considere usar @ org.junit.Rule porque le brinda más flexibilidad. ExternalResource (a partir de 4.7) es la regla que más le interesará si gestiona conexiones. Además, si desea un orden de ejecución garantizado de sus reglas, use una RuleChain (a partir de 4.10). Creo que todo esto estaba disponible cuando se hizo esta pregunta. El ejemplo de código a continuación se copia de los javadocs de ExternalResource.
fuente