Domanda

Ho una classe base astratta, che utilizzo come base per i miei test unitari (TestNG 5.10).In questa classe inizializzo l'intero ambiente per i miei test, impostando le mappature dei database, ecc.Questa classe astratta ha un metodo con a @BeforeClass annotazione che esegue l'inizializzazione.

Successivamente, estendo quella classe con classi specifiche in cui ho @Test metodi e anche @BeforeClass metodi.Questi metodi eseguono l'inizializzazione specifica della classe dell'ambiente (ad es.inserire alcuni record nel database).

Come posso far rispettare un ordine specifico del @BeforeClass metodi annotati?Ho bisogno che quelli della classe base astratta vengano eseguiti prima di quelli della classe estesa.

Esempio:

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

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

    @Test
    doTests() {...}
}

Ordine previsto:

A.doInitialization
B.doSpecificInitialization
B.doTests

Ordine effettivo:

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

Soluzione

Non mettere il @BeforeClass sulla classe abstract. Chiamare da ogni sottoclasse.

abstract class A {
    void doInitialization() {}
}

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

    @Test
    void doTests() {}
}

Sembra TestNG ha @BeforeClass(dependsOnMethods={"doInitialization"}) - fare un tentativo.

Altri suggerimenti

modifica:. Risposta di seguito è per JUnit , ma lascio qui in ogni caso, perché potrebbe essere utile

Secondo il JUnit api : "I @BeforeClass metodi di superclassi verranno eseguiti prima di quelli della classe corrente ".

Ho provato questo, e sembra funzionare per me.

Tuttavia, come @Odys cita di seguito, per JUnit è necessario avere due metodi chiamati in modo diverso anche se, come fare altrimenti comporterà solo il metodo della sottoclasse in esecuzione perché il genitore sarà oscurato.

Ho aggiunto public alla classe astratta e TestNG (6.0.1) eseguito il doInitialization () prima doTests. TestNG non esegue doInitialization() se tolgo public dalla classe A.

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

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

Ho appena provato il tuo esempio con 5.11 e ottengo il @BeforeClass della classe base invocato prima.

È possibile inviare il file testng.xml? Forse si sta specificando sia A che B lì, mentre solo B è necessaria.

Non esitate a seguito alle TestNG-users mailing-list e siamo in grado di dare uno sguardo più da vicino il problema.

- Cedric

Ho appena passato attraverso questo e ha trovato un altro modo per raggiungere questo obiettivo. Basta usare alwaysRun su @BeforeClass o @BeforeMethod nella classe astratta, funziona come ci si aspetterebbe.

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

Quando eseguo da: JUnitCore.runClasses (TestClass.class); Si eseguirà il genitore correttamente, prima che il bambino (non è necessario super.SetUpBeforeClass (); ) Se lo si esegue da Eclipse: Per qualche ragione non riesce a eseguire la classe di base. Il lavoro intorno: Chiamare la classe base esplicitamente: ( BaseTest.setUpBeforeClass (); )  Si consiglia di avere una bandiera nella classe base nel caso in cui lo si esegue da un'applicazione, per determinare se è già messa a punto o meno. Quindi viene eseguito solo una volta, se lo si esegue tramite due metodi possibili (ad esempio da Eclipse per la prova personale, e attraverso ANT per un rilascio build).

Questo sembra essere un bug con Eclipse, o risultati almeno imprevisti ..

Per JUnit : Come @fortega ha detto: Secondo l'api JUnit: "I metodi di @BeforeClass superclassi verranno eseguiti prima di quelli della classe corrente"

Ma attenzione a non fare il nome entrambi i metodi con lo stesso nome . Dal momento che in questo caso il metodo di genitore sarà nascosto dai genitori del bambino. Source.

Che ne dite di avere il vostro metodo di @BeforeClass chiamare un metodo vuoto specificBeforeClass (), che può o non può essere sovrascritto da classi secondarie in questo modo:

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 può essere utilizzato.

es. in caso di primavera (AbstractTestNGSpringContextTests)

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

Controlla la tua istruzione import. Dovrebbe essere

import org.testng.annotations.BeforeClass;

non

import org.junit.BeforeClass;

Perché non si tenta di creare un metodo astratto doSpecialInit () nella classe super, chiamare dal proprio BeforeClass metodo annotato nella superclasse.

Quindi sviluppatori ereditare la classe è costretto a implementare questo metodo.

C'è un'altra soluzione facile qui.

La mia situazione particolare, è che ho bisogno di iniettare servizi finto da "BeforeClass" nella sottoclasse prima "BeforeClass" in viene eseguita la superclasse.

Per fare questo - è sufficiente utilizzare un @ClassRule nella sottoclasse

.

Ad esempio:

@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
    }
};

Spero che questo aiuta. Questo può eseguire in modo efficace impostazione statica in modo "inverso".

Ho affrontato un problema simile oggi, l'unica differenza era che la classe Base non era astratta

Ecco il mio caso

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

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

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

È avvenuto che a @BeforeClass il metodo della classe A non è mai stato eseguito.

  • A.doInitialization() -> QUESTO NON È MAI STATO ESEGUITO in silenzio
  • B.doSpecificInitialization()
  • B.doTest()

Giocando con i modificatori della privacy ho scoperto che TestNG non verrà eseguito UN @BeforeClass metodo annotato dalla classe ereditata se un metodo non è visibile da un erede di classe

Quindi funzionerà:

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

Di conseguenza accade quanto segue:

  • A.doInizializzazione()
  • B.doSpecificInitialization()
  • B.doTest()

Questo funziona per me -

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

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

       //do class specific init

    }   

    @Test
    doTests() {...}
}

Nel mio caso (JUnit) ho gli stessi metodi chiamati setup () nella classe base e la classe derivata. In questo caso, solo il metodo della classe derivata si chiama, e ce l'ho chiamare il metodo della classe base.

Un modo migliore e più pulito per raggiungere questo obiettivo utilizzando l'ereditarietà può essere come segue -

abstract class A {

    @BeforeClass
    void doInitialization() {}
}

class B extends A {

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

    @Test
    void doTests() {}
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top