Eu tenho um conjunto de testes de integração. Eu tenho uma IntegrationTestBase
aula para todos os meus testes estenderem. Essa classe base possui um método @Before
( public void setUp()
) e @After
( public void tearDown()
) para estabelecer conexões API e DB. O que venho fazendo é substituir esses dois métodos em cada caso de teste e chamar super.setUp()
e super.tearDown()
. No entanto, isso pode causar problemas se alguém esquecer de chamar o super ou colocá-lo no lugar errado e uma exceção for lançada e eles esquecerem de chamar super no finalmente ou algo assim.
O que eu quero fazer é criar os métodos setUp
e tearDown
na classe base final
e, em seguida, basta adicionar nossos próprios métodos @Before
e anotados @After
. Fazendo alguns testes iniciais, parece sempre chamar nesta ordem:
Base @Before
Test @Before
Test
Test @After
Base @After
mas estou um pouco preocupado com o fato de o pedido não ser garantido e de causar problemas. Olhei em volta e não vi nada sobre o assunto. Alguém sabe se eu posso fazer isso e não tenho problemas?
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?* }
}
fonte
MyTest
desaparecido é umextends
?Respostas:
Sim, esse comportamento é garantido:
@Before
:@After
:fonte
@Before
métodos não é garantida. Se houver 10@Before
métodos, cada um deles pode ser executado em qualquer ordem; imediatamente antes de qualquer outro método.@Before
e são@After
executados antes de qualquer outro método de classe (uma vez por método) ou imediatamente antes e depois de todo o conjunto de métodos de classe (uma vez por classe)?junit-4.12
.Uma pegadinha em potencial que já me mordeu:
Eu gosto de ter no máximo um
@Before
método em cada classe de teste, porque a ordem de execução dos@Before
métodos definidos em uma classe não é garantida. Normalmente, chamarei esse métodosetUpTest()
.Mas, embora
@Before
esteja documentado comoThe @Before methods of superclasses will be run before those of the current class. No other ordering is defined.
, isso só se aplica se cada método marcado com@Before
tiver um nome exclusivo na hierarquia de classes.Por exemplo, eu tive o seguinte:
Eu esperava
AbstractFooTest.setUpTest()
correr antesFooTest.setUpTest()
, mas apenasFooTest.setupTest()
foi executado.AbstractFooTest.setUpTest()
não foi chamado.O código deve ser modificado da seguinte maneira para funcionar:
fonte
@Before
/@After
métodos na classe basefinal
, para que o compilador se queixe se você (acidentalmente) tentar substituí-los na subclasse.@Before
métodos marcados serão ignorados se uma subclasse também tiver um@Before
método.Penso que, com base na documentação
@Before
e@After
na conclusão correta, é dar nomes únicos aos métodos. Eu uso o seguinte padrão nos meus testes:e
dar como resultado
Vantagem dessa abordagem: os usuários da classe AbstractBaseTest não podem substituir os métodos setUp / tearDown por acidente. Se quiserem, precisam saber o nome exato e podem fazê-lo.
(Menor) desvantagem dessa abordagem: os usuários não conseguem ver que há coisas acontecendo antes ou depois de sua configuração / desmontagem. Eles precisam saber que essas coisas são fornecidas pela classe abstrata. Mas suponho que essa seja a razão pela qual eles usam a classe abstrata
fonte
Se você inverter as coisas, poderá declarar o abstrato da classe base e os descendentes declararão os métodos setUp e tearDown (sem anotações) que são chamados nos métodos anotados setUp e tearDown da classe base.
fonte
Você pode usar a
@BeforeClass
anotação para garantir quesetup()
sempre seja chamado primeiro. Da mesma forma, você pode usar a@AfterClass
anotação para garantir quetearDown()
sempre seja chamado por último.Isso geralmente não é recomendado, mas é suportado .
Não é exatamente o que você deseja - mas essencialmente manterá sua conexão com o banco de dados aberta o tempo todo em que seus testes estiverem sendo executados e depois fechá-la de uma vez por todas no final.
fonte
setupDB()
ecloseDB()
e marcando-as com@BeforeClass
e@AfterClass
e substituir o seu / antes depois métodos comsetup()
etearDown()
@BeforeClass
e@AfterClass
precisam ser estáticos. E o caso, quando queremos usar variáveis de instância dentro desses métodos?@BeforeClass
com o Powermock: ele funciona apenas na primeira execução de teste. Veja esta edição: github.com/powermock/powermock/issues/398Esta não é uma resposta para a pergunta do slogan, mas é uma resposta para os problemas mencionados no corpo da pergunta. Em vez de usar @Before ou @After, analise o uso de @ org.junit.Rule, pois oferece mais flexibilidade. ExternalResource (a partir de 4.7) é a regra na qual você estará mais interessado se estiver gerenciando conexões. Além disso, se você deseja garantir a ordem de execução de suas regras, use um RuleChain (a partir da versão 4.10). Acredito que todos eles estavam disponíveis quando essa pergunta foi feita. O exemplo de código abaixo é copiado dos javadocs do ExternalResource.
fonte