test debug after java unit-testing testng

java - debug - testng test



@BeforeClass and inheritance-orden de ejecuciĆ³n (14)

Tengo una clase base abstracta, que utilizo como base para mis pruebas unitarias (TestNG 5.10). En esta clase, inicializo todo el entorno para mis pruebas, estableciendo mapeos de bases de datos, etc. Esta clase abstracta tiene un método con una anotación @BeforeClass que realiza la inicialización.

A continuación, @Test esa clase con clases específicas en las que tengo métodos @Test y también métodos @BeforeClass . Estos métodos hacen la inicialización del entorno específica de la clase (por ejemplo, poner algunos registros en la base de datos).

¿Cómo puedo aplicar un orden específico de los métodos anotados @BeforeClass ? Necesito que los de la clase base abstracta se ejecuten antes que los de la clase extendida.

Ejemplo:

abstract class A { @BeforeClass doInitialization() {...} } class B extends A { @BeforeClass doSpecificInitialization() {...} @Test doTests() {...} }

Orden esperado:

A.doInitialization B.doSpecificInitialization B.doTests

Orden real:

B.doSpecificInitialization // <- crashes, as the base init is missing (A.doInitialization // <---not executed B.doTests) // <-/


¿Por qué no intentas crear un método abstracto doSpecialInit () en tu súper clase, llamado desde tu método anotado BeforeClass en superclase?

Entonces los desarrolladores que heredan su clase se ven obligados a implementar este método.


¿Qué tal si tu método @BeforeClass llama a un método emptyBeforeClass () vacío que puede ser sobrescrito o no por subclases como sigue?

public class AbstractTestClass { @BeforeClass public void generalBeforeClass() { // do stuff specificBeforeClass(); } protected void specificBeforeClass() {} } public class SpecificTest { @Override protected void specificBeforeClass() { // Do specific stuff } // Tests }


Añadí public a la clase abstracta y TestNG (6.0.1) ejecutó doInitialization () antes de doTests . TestNG no ejecuta doInitialization() si doInitialization() public de la clase A.

public abstract class A { @BeforeClass doInitialization() {...} } class B extends A { @Test doTests() {...} }


Acabo de pasar por esto y encontré una forma más de lograr esto. Solo use alwaysRun en @BeforeClass o @BeforeMethod en la clase abstracta, funciona como es de esperar.

public class AbstractTestClass { @BeforeClass(alwaysRun = true) public void generalBeforeClass() { // do stuff specificBeforeClass(); } }


Acabo de probar tu ejemplo con 5.11 y obtengo primero @BeforeClass de la clase base invocada.

¿Puedes publicar tu archivo testng.xml? Tal vez estés especificando A y B allí, mientras que solo B es necesario.

Siéntase libre de hacer un seguimiento de la lista de correo de usuarios de testng y podemos analizar su problema de cerca.

- Cedric


Cuando ejecuto desde: JUnitCore.runClasses (TestClass.class); Ejecutará el elemento primario correctamente, antes que el elemento secundario (No necesita super.SetUpBeforeClass (); ) Si lo ejecuta desde Eclipse: Por algún motivo, no ejecuta la clase base. El rodeo : llame explícitamente a la clase base: ( BaseTest.setUpBeforeClass (); ) Puede querer tener un indicador en la clase base en caso de que lo ejecute desde una aplicación, para determinar si ya está configurado o no. Por lo tanto, solo se ejecuta una vez si lo ejecuta a través de ambos métodos posibles (por ejemplo, desde eclipse para pruebas personales, y a través de ANT para una versión de compilación).

Esto parece ser un error con Eclipse, o al menos resultados inesperados.


En mi caso (JUnit) tengo los mismos métodos llamados setup () en la clase base y la clase derivada. En este caso, solo se llama al método de la clase derivada, y lo hago llamar al método de clase base.


Hay otra solución fácil aquí.

Mi situación particular es que necesito inyectar servicios simulados desde "BeforeClass" en la subclase antes de que se ejecute "BeforeClass" en la superclase.

Para hacer esto, simplemente use una @ClassRule en la subclase.

Por ejemplo:

@ClassRule public static ExternalResource mocksInjector = new ExternalResource() { @Override protected void before() { // inject my mock services here // Note: this is executed before the parent class @BeforeClass } };

Espero que esto ayude. Esto puede ejecutar de manera efectiva la configuración estática en orden "inverso".


No coloque @BeforeClass en la clase abstract . Llamarlo desde cada subclase.

abstract class A { void doInitialization() {} } class B extends A { @BeforeClass void doSpecificInitialization() { super.doInitialization(); } @Test void doTests() {} }

Parece que TestNG tiene @BeforeClass(dependsOnMethods={"doInitialization"}) - pruébalo.


Una forma mejor y más limpia de lograr esto utilizando la herencia puede ser la siguiente:

abstract class A { @BeforeClass void doInitialization() {} } class B extends A { @Override @BeforeClass void doInitialization() { super.doInitialization(); } @Test void doTests() {} }


Verifique su declaración de importación. Debería ser

import org.testng.annotations.BeforeClass;

no

import org.junit.BeforeClass;


dependsOnMethod se puede usar.

por ejemplo, en caso de Spring ( AbstractTestNGSpringContextTests )

@BeforeClass(alwaysRun = true, dependsOnMethods = "springTestContextPrepareTestInstance")


Para JUnit : Como @fortega ha mencionado: de acuerdo con la API de JUnit: "Los métodos @BeforeClass de las superclases se ejecutarán antes que los de la clase actual".

Pero tenga cuidado de no nombrar ambos métodos con el mismo nombre . Dado que en este caso el padre padre ocultará el método principal. Source


editar: la respuesta a continuación es para JUnit , pero lo dejaré aquí de todos modos, porque podría ser útil.

De acuerdo con la API de JUnit : "Los métodos @BeforeClass de las superclases se ejecutarán antes que los de la clase actual".

Probé esto, y parece funcionar para mí.

Sin embargo, como @Odys menciona a continuación, para JUnit necesita tener los dos métodos denominados de forma diferente, ya que al hacerlo, de lo contrario, solo se ejecutará el método de la subclase porque el padre se sombreará.