Pergunta

Eu tenho uma classe base abstrata, que uso como base para meus testes de unidade (Testng 5.10). Nesta aula, inicializo todo o ambiente para meus testes, configurando mapeamentos de banco de dados, etc. Esta classe abstrata tem um método com um @BeforeClass anotação que faz a inicialização.

Em seguida, estendo a aula com classes específicas em que tenho @Test métodos e também @BeforeClass métodos. Esses métodos fazem a inicialização específica da classe do ambiente (por exemplo, coloca alguns registros no banco de dados).

Como posso fazer cumprir uma ordem específica do @BeforeClass Métodos anotados? Eu preciso que os da classe base abstrata sejam executados antes dos da classe prolongada.

Exemplo:

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

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

    @Test
    doTests() {...}
}

Ordem esperada:

A.doInitialization
B.doSpecificInitialization
B.doTests

Ordem real:

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

Solução

Não coloque o @BeforeClass no abstract classe. Chame de cada subclasse.

abstract class A {
    void doInitialization() {}
}

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

    @Test
    void doTests() {}
}

Parece que o testng tem @BeforeClass(dependsOnMethods={"doInitialization"}) - De uma chance.

Outras dicas

editar: Resposta abaixo é para Junit, mas vou deixar aqui de qualquer maneira, porque pode ser útil.

De acordo com Junit API: "Os métodos @BeFeClass de superclasses serão executados antes daqueles que a classe atual".

Eu testei isso, e parece funcionar para mim.

No entanto, como @odys menciona abaixo, para Junit, você precisa ter o Dois métodos nomeados de maneira diferente embora, como fazer o contrário, resulte apenas o método da subclasse sendo executado porque o pai será sombreado.

Eu adicionei public para a classe abstrata e testng (6.0.1) executaram a doinitialização () antes doTests. Testng não executa doInitialization() Se eu remover public da classe A.

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

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

Acabei de experimentar o seu exemplo com o 5.11 e recebo o @BeForEClass da classe base invocada primeiro.

Você pode postar seu arquivo testng.xml? Talvez você esteja especificando A e B lá, enquanto apenas B é necessário.

Sinta-se à vontade para acompanhar a lista de correspondência dos usuários de teste e podemos examinar mais de perto o seu problema.

- Cedric

Acabei de passar por isso e encontrei mais uma maneira de conseguir isso. Apenas use alwaysRun sobre @BeforeClass ou @BeforeMethod Na classe abstrata, funciona como seria de esperar.

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

Quando eu corro de: Junitcore.runclasses (testclass.class);Ele executará o pai corretamente, antes da criança (você não precisa super.setupBeFeClass ();) Se você o executar do Eclipse: por algum motivo, ele não executa a classe base. O trabalho por aí: ligue explícito na classe base: (Bastest.setupBeforeClass ();) Você pode querer ter um sinalizador na classe base, caso o execute a partir de um aplicativo, para determinar se ele já está configurado ou não. Portanto, ele é executado apenas uma vez se você o executar através de ambos os métodos possíveis (como do Eclipse para testes pessoais e através da Ant para uma versão de compilação).

Isso parece ser um bug do eclipse, ou pelo menos resultados inesperados.

Para Junit: Como @fortaga mencionou: De acordo com a API JUNIT: "Os métodos @BeFeClass de superclasses serão executados antes daqueles que a classe atual".

Mas tenha cuidado não para citar os dois métodos com o mesmo nome. Como neste caso, o método pai será oculto pelos pais da criança. Fonte.

Que tal ter seu método @beforeClass chamar um método vazio de especificeforeClass () que pode ou não ser sobrescrito por sub -classes como assim:

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 pode ser usado.

por exemplo, em caso de primavera (AbstractTestNGSpringContextTests)

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

Verifique sua declaração de importação. Deveria ser

import org.testng.annotations.BeforeClass;

não

import org.junit.BeforeClass;

Por que você não tenta criar um método abstrato DosPeCialinit () em sua super classe, chamado do seu método anotado no BeforeClass na Superclass.

Portanto, os desenvolvedores herdando sua classe são forçados a implementar esse método.

Há outra solução fácil aqui.

Minha situação específica é que preciso injetar serviços simulados de "beforeClass" na subclasse antes "beforeClass" na superclasse é executado.

Para fazer isso - basta usar um @ClassRule na subclasse.

Por exemplo:

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

Eu espero que isso ajude. Isso pode efetivamente executar a configuração estática na ordem "reversa".

Eu enfrentei um problema semelhante hoje, a única diferença foi uma classe base não era abstrata

Aqui está o meu caso

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

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

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

Ocorreu que um @BeforeClass O método da classe A nunca foi executado.

  • A.Doinitialization () -> Isso nunca foi executado silenciosamente
  • B. Dosespecificinitialização ()
  • B.DOTESTS ()

Brincando com modificadores de privacidade, encontrei que testng não será executado uma @BeforeClass Método anotado de classe herdada Se um método não for visível de um infectorado de classe

Então isso vai funcionar:

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

Como resultado, acontece:

  • A.Doinitialization ()
  • B. Dosespecificinitialização ()
  • B.DOTESTS ()

Isso funciona para mim -

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

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

       //do class specific init

    }   

    @Test
    doTests() {...}
}

No meu caso (JUNIT), tenho os mesmos métodos chamados setup () na classe base e na classe derivada. Nesse caso O método da classe derivada é chamado, e eu o chamo de método de classe base.

Uma maneira melhor e mais limpa de conseguir isso usando a herança pode ser como seguinte -

abstract class A {

    @BeforeClass
    void doInitialization() {}
}

class B extends A {

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

    @Test
    void doTests() {}
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top