Tengo una suite de prueba de integración. Tengo una IntegrationTestBaseclase 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 setUpy tearDownen la clase base finaly luego simplemente agregar nuestros propios métodos @Beforey 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

MyTestfalta unextends?Respuestas:
Sí, este comportamiento está garantizado:
@Before:@After:fuente
@Beforemétodos no está garantizado. Si hay 10@Beforemétodos, cada uno de ellos puede ejecutarse en cualquier orden; justo antes de cualquier otro método.@Beforey@Afterantes 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
@Beforemétodo en cada clase de prueba, porque el orden de ejecución de los@Beforemétodos definidos dentro de una clase no está garantizado. Por lo general, llamaré a tal métodosetUpTest().Pero, aunque
@Beforeestá 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@Beforetiene 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/@Aftermétodos en la clase basefinal, por lo que el compilador se quejará si (accidentalmente) intenta anularlos en la subclase.@Beforemétodos marcados se ignorarán si una subclase también tiene un@Beforemétodo.Creo que basado en la documentación de la
@Beforey@Afterla 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
@BeforeClassanotación para asegurarse de quesetup()siempre se llame primero. Del mismo modo, puede usar la@AfterClassanotació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@BeforeClassy@AfterClassy reemplazar sus métodos antes / después consetup()ytearDown()@BeforeClassy@AfterClassdeben ser estáticos. ¿Qué pasa con el caso, cuando queremos usar variables de instancia dentro de estos métodos?@BeforeClasscon 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