Anotação @TestInstance na JUnit 5

Anotação @TestInstance na JUnit 5

1. Introdução

As classes de teste geralmente contêm variáveis ​​de membro referentes ao sistema em teste, zombarias ou recursos de dados usados ​​no teste. By default, both JUnit 4 and 5 create a new instance of the test class before running each test method. Isso fornece uma separação clara de estado entre os testes.

Neste tutorial, vamos aprender comoJUnit 5 nos permite modificar o ciclo de vida da classe de teste usando a anotação@TestInstance. Também veremos como isso pode nos ajudar a gerenciar grandes recursos ou relacionamentos mais complexos entre os testes.

2. Ciclo de vida de teste padrão

Vamos começar observando o ciclo de vida da classe de teste padrão, comum ao JUnit 4 e 5:

class AdditionTest {

    private int sum = 1;

    @Test
    void addingTwoReturnsThree() {
        sum += 2;
        assertEquals(3, sum);
    }

    @Test
    void addingThreeReturnsFour() {
        sum += 3;
        assertEquals(4, sum);
    }
}

Este código poderia ser facilmente um código de teste JUnit 4 ou 5, exceto a palavra-chavepublic ausente que o JUnit 5 não requer.

Esses testes são aprovados porque uma nova instância deAdditionTest é criada antes de cada método de teste ser chamado. Isso significa que o valor da variávelsum é sempre definido como1 antes da execução de cada teste.

Se houvesse apenas uma instância compartilhada do objeto de teste, a variávelsum manteria seu estado após cada teste. Como resultado, o segundo teste falharia.

3. As anotações @BeforeClasse@BeforeAll

Há momentos em que precisamos que um objeto exista em vários testes. Vamos imaginar que gostaríamos de ler um arquivo grande para usar como dados de teste. Como pode ser demorado repetir isso antes de cada teste, podemos preferir lê-lo uma vez e mantê-lo por todo o equipamento de teste.

O JUnit 4 aborda isso com sua anotação@BeforeClass:

private static String largeContent;

@BeforeClass
public static void setUpFixture() {
    // read the file and store in 'largeContent'
}

Devemos observar quewe have to make the variables and the methods annotated with JUnit 4’s @BeforeClass static.

O JUnit 5 fornece uma abordagem diferente. Ele fornece a anotação@BeforeAll que é usada em uma função estática, para trabalhar com membros estáticos da classe.

No entanto,@BeforeAll também pode ser usado com uma função de instância e membros de instância se o ciclo de vida da instância de teste for alterado paraper-class.

4. A anotação@TestInstance

A anotação@TestInstance nos permite configurar o ciclo de vida dos testes JUnit 5.

@TestInstance has two modes. Um éLifeCycle.PER_METHOD (o padrão). O outro éLifeCycle.PER_CLASS. O último nos permite pedir ao JUnit para criar apenas uma instância da classe de teste e reutilizá-la entre os testes.

Vamos anotar nossa classe de teste com a anotação@TestInstance e usar o modoLifeCycle.PER_CLASS:

@TestInstance(LifeCycle.PER_CLASS)
class TweetSerializerUnitTest {

    private String largeContent;

    @BeforeAll
    void setUpFixture() {
        // read the file
    }

}

Como podemos ver, nenhuma das variáveis ​​ou funções é estática. Podemos usar um ciclo de vida deinstance method for @BeforeAll when we use the PER_CLASS.

Também devemos observar que as alterações feitas no estado das variáveis ​​de instância por um teste agora serão visíveis para os outros.

5. Usos de@TestInstance(PER_CLASS)

5.1. Recursos caros

Essa anotação é útil quando a instanciação de uma classe antes de cada teste é bastante cara. Um exemplo pode ser estabelecer uma conexão com o banco de dados ou carregar um arquivo grande.

A solução disso anteriormente levou a uma combinação complexa de variáveis ​​estáticas e de instância, que agora é mais limpa com uma instância de classe de teste compartilhada.

5.2. Estado deliberado de compartilhamento

Sharing state is usually an anti-pattern in unit tests, but can be useful in integration tests. O ciclo de vida por classe oferece suporte a testes sequenciais que compartilham o estado intencionalmente. Isso pode ser necessário para evitar que testes posteriores tenham que repetir as etapas de testes anteriores, especialmente se a lentidão do sistema em teste for lenta.

Ao compartilhar o estado, para executar todos os testes em sequência, o JUnit 5 nos fornece a anotação de nível de tipo@TestMethodOrder. Então podemos usar a anotação@Order nos métodos de teste para executá-los na ordem de nossa escolha.

@TestMethodOrder(OrderAnnotation.class)
class OrderUnitTest {

    @Test
    @Order(1)
    void firstTest() {
        // ...
    }

    @Test
    @Order(2)
    void secondTest() {
        // ...
    }

}

5.3. Compartilhando algum estado

O desafio de compartilhar a mesma instância da classe de teste é que alguns membros talvez precisem ser limpos entre os testes e alguns talvez precisem ser mantidos durante todo o teste.

Podemos redefinir as variáveis ​​que precisam ser limpas entre os testes com métodos anotados com@BeforeEach ou@AfterEach.

6. Conclusão

Neste tutorial, aprendemos sobre a anotação@TestInstance e como ela pode ser usada para configurar o ciclo de vida de testes JUnit 5.

Também vimos por que seria útil compartilhar uma única instância da classe de teste, em termos de manipulação de recursos compartilhados ou gravação deliberada de testes seqüenciais.

Como sempre, o código para este tutorial pode serfound on GitHub.