Pregunta

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

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

¿Cómo puedo hacer cumplir una orden específica del @BeforeClass métodos anotados?Necesito que los de la clase base abstracta se ejecuten antes que los de la clase extensible.

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)                // <-/
¿Fue útil?

Solución

No coloque el @BeforeClass en la clase abstract. Llamaremos a partir de 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"}) - darle una oportunidad.

Otros consejos

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

De acuerdo con la JUnit API : "El @BeforeClass métodos de superclases se llevará a cabo antes que los de la clase actual ".

He probado esto, y parece que funciona para mí.

Sin embargo, como se menciona a continuación @Odys, por JUnit es necesario tener los dos métodos denominados de forma diferente aunque como hacer lo contrario dará lugar a sólo el método que se está ejecutando subclase porque será ensombrecido el padre.

He añadido public a la clase abstracta y TestNG (6.0.1) ejecuta el doInitialization () antes de doTests. TestNG no ejecuta doInitialization() si quito public de clase A.

public abstract class A {
 @BeforeClass
 doInitialization() {...}
}

class B extends A {    
 @Test
 doTests() {...}
}

Me acaba de intentar su ejemplo, con 5.11 y consigo los @BeforeClass de la clase base invocada por primera vez.

Se puede publicar su archivo testng.xml? Tal vez está especificando tanto A como B allí, mientras que sólo el B es necesaria.

No dude en dar seguimiento a la lista de correo de los usuarios TestNG y podemos echar un vistazo más de cerca a su problema.

- Cedric

Me acaba de ir a través de este y encontró una forma más para lograrlo. Sólo tiene que utilizar alwaysRun en @BeforeClass o @BeforeMethod en la clase abstracta, funciona como era de esperar.

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

Cuando corro de: JUnitCore.runClasses (TestClass.class); Se ejecutará la matriz correctamente, antes de que el niño (No es necesario super.SetUpBeforeClass (); ) Si se ejecuta desde Eclipse: Por alguna razón no se ejecuta la clase base. El trabajo en torno a: Llame a la clase base explícitamente: ( BaseTest.setUpBeforeClass (); )  Es posible que desee tener una bandera en la clase base en caso de que se ejecuta desde una aplicación, para determinar si ya se ha configurado o no. Por lo que sólo se ejecuta una vez si se ejecuta a través de dos métodos posibles (por ejemplo, a partir del eclipse para las pruebas de personal, ya través de la hormiga por un comunicado de acumulación).

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

Para JUnit : Como se ha mencionado @fortega: De acuerdo con la API de JUnit: "Los métodos @BeforeClass de superclases se llevará a cabo antes que los de la clase actual"

Pero tenga cuidado no nombrar los dos métodos con el mismo nombre . Dado que en este caso el método padres se ocultará por el padre del niño. Fuente .

¿Qué hay de tener su método @BeforeClass llamar un método vacío specificBeforeClass () que puede o no puede ser sobrescrito por subclases de esta manera:

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

  protected void specificBeforeClass() {}
}

public class SpecificTest {
  @Override
  protected void specificBeforeClass() {
    // Do specific stuff
  }

  // Tests
}

dependsOnMethod se puede utilizar.

por ejemplo. en el caso de la primavera (AbstractTestNGSpringContextTests)

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

Compruebe su declaración de importación. Debe ser

import org.testng.annotations.BeforeClass;

no

import org.junit.BeforeClass;

¿Por qué no intenta crear un método abstracto doSpecialInit () en su super clase, llamada de su método anotado BeforeClass en superclase.

Así que heredan desarrolladores de su clase se ve obligado a poner en práctica este método.

Hay otra solución fácil aquí.

Mi situación particular es que necesito para inyectar servicios de simulacros de "BeforeClass" en la subclase antes "BeforeClass" en el que se ejecuta la superclase.

Para hacer esto -. Sólo tiene que utilizar un @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 se puede ejecutar con eficacia configuración estática en "marcha atrás" orden.

Me he enfrentado a un problema similar en la actualidad, la única diferencia era una clase base abstracta no era

Aquí está mi caso

public class A {
    @BeforeClass
    private void doInitialization() {...}
}

public class B extends A {
    @BeforeClass
    private void doSpecificInitialization() {...}

    @Test
    public void doTests() {...}
}

Se le ocurrió que un método @BeforeClass de la clase A nunca fue ejecutado.

  • A.doInitialization () -> esto nunca se EJECUTADO silencio
  • B.doSpecificInitialization ()
  • B.doTests ()

Jugando con modificadores de privacidad encontré que TestNG no ejecutará un método anotado @BeforeClass de clase heredada si un método no es visible desde una clase-heredera

Así que este trabajo:

public class A {
    @BeforeClass
    private void doInitialization() {...}
}

public class B extends A {
    @BeforeClass
    //Here a privacy modifier matters -> please make sure your method is public or protected so it will be visible for ancestors
    protected void doSpecificInitialization() {...}

    @Test
    public void doTests() {...}
}

A medida que pasa el siguiente resultado:

  • A.doInitialization ()
  • B.doSpecificInitialization ()
  • B.doTests ()

Esto funciona para mí -

abstract class A {
    @BeforeClass
    doInitialization() {...}
}

class B extends A {
    @Override
    @BeforeClass
    doInitialization() { 

       //do class specific init

    }   

    @Test
    doTests() {...}
}

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

A mejor y de manera más limpia para lograr esto utilizando la herencia puede ser de la siguiente manera -

abstract class A {

    @BeforeClass
    void doInitialization() {}
}

class B extends A {

    @Override
    @BeforeClass
    void doInitialization() {
        super.doInitialization();
    }

    @Test
    void doTests() {}
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top