@Before vs @BeforeClass vs @BeforeEach vs @BeforeAll
1. Introdução
Neste breve tutorial, vamos explicar as diferenças entre as anotações@Before,@BeforeClass,@BeforeEache@BeforeAll na JUnit 4 e 5 - com exemplos práticos de como para usá-los.
Também cobriremos brevemente suas@After anotações complementares.
Vamos começar com o JUnit 4.
2. @Before
Methods annotated with the @Before annotation are executed before each test. Isso é útil quando queremos executar algum código comum antes de executar um teste.
Vejamos um exemplo em que inicializamos uma lista e adicionamos alguns valores:
@RunWith(JUnit4.class)
public class BeforeAndAfterAnnotationsUnitTest {
// ...
private List list;
@Before
public void init() {
LOG.info("startup");
list = new ArrayList<>(Arrays.asList("test1", "test2"));
}
@After
public void finalize() {
LOG.info("finalize");
list.clear();
}
}
Observe que também adicionamos outro método anotado com@After para limpar a lista após a execução de cada teste.
Depois disso, vamos adicionar alguns testes para verificar o tamanho da nossa lista:
@Test
public void whenCheckingListSize_thenSizeEqualsToInit() {
LOG.info("executing test");
assertEquals(2, list.size());
list.add("another test");
}
@Test
public void whenCheckingListSizeAgain_thenSizeEqualsToInit() {
LOG.info("executing another test");
assertEquals(2, list.size());
list.add("yet another test");
}
Nesse caso,it’s crucial to make sure that test environment is properly set up before running each test, pois a lista é modificada durante cada execução do teste.
Se olharmos a saída do log, podemos verificar se os métodosinitefinalize foram executados uma vez por teste:
... startup
... executing another test
... finalize
... startup
... executing test
... finalize
3. @BeforeClass
Quando queremos executar uma operação comum cara antes de cada teste,it’s preferable to execute it only once before running all tests using @BeforeClass. Alguns exemplos de operações caras comuns são a criação de uma conexão com o banco de dados ou a inicialização de um servidor.
Vamos criar uma classe de teste simples que simula a criação de uma conexão de banco de dados:
@RunWith(JUnit4.class)
public class BeforeClassAndAfterClassAnnotationsUnitTest {
// ...
@BeforeClass
public static void setup() {
LOG.info("startup - creating DB connection");
}
@AfterClass
public static void tearDown() {
LOG.info("closing DB connection");
}
}
Observe quethese methods have to be static, então eles serão executados antes de executar os testes da classe.
Como fizemos antes, vamos adicionar alguns testes simples:
@Test
public void simpleTest() {
LOG.info("simple test");
}
@Test
public void anotherSimpleTest() {
LOG.info("another simple test");
}
Desta vez, se dermos uma olhada na saída do log, podemos verificar se os métodossetupetearDown foram executados apenas uma vez:
... startup - creating DB connection
... simple test
... another simple test
... closing DB connection
4. @BeforeEach e@BeforeAll
@BeforeEach and @BeforeAll are the JUnit 5 equivalents of @Before and @BeforeClass. Essas anotações foram renomeadas com nomes mais claros para evitar confusão.
Vamos duplicar nossas classes anteriores usando essas novas anotações, começando com as anotações@BeforeEache@AfterEach:
@RunWith(JUnitPlatform.class)
class BeforeEachAndAfterEachAnnotationsUnitTest {
// ...
private List list;
@BeforeEach
void init() {
LOG.info("startup");
list = new ArrayList<>(Arrays.asList("test1", "test2"));
}
@AfterEach
void finalize() {
LOG.info("finalize");
list.clear();
}
// ...
}
Se verificarmos os logs, podemos confirmar que funciona da mesma maneira que com as anotações@Beforee@After:
... startup
... executing another test
... finalize
... startup
... executing test
... finalize
Finalmente, vamos fazer o mesmo com a outra classe de teste para ver as anotações@BeforeAlle@AfterAll em ação:
@RunWith(JUnitPlatform.class)
public class BeforeAllAndAfterAllAnnotationsUnitTest {
// ...
@BeforeAll
public static void setup() {
LOG.info("startup - creating DB connection");
}
@AfterAll
public static void tearDown() {
LOG.info("closing DB connection");
}
// ...
}
E a saída é a mesma da anotação antiga:
... startup - creating DB connection
... simple test
... another simple test
... closing DB connection
5. Conclusão
Neste artigo, mostramos as diferenças entre as anotações@Before,@BeforeClass,@BeforeEache@BeforeAll no JUnit e quando cada uma delas deve ser usada.
Como sempre, o código-fonte completo dos exemplos está disponívelover on GitHub.