Asserções personalizadas com AssertJ

Asserções personalizadas com AssertJ

 

1. Visão geral

Neste tutorial, vamos percorrer a criação de asserçõesAssertJ personalizadas; os fundamentos do AssertJcan be found here.

Simplificando, asserções personalizadas permitem criar asserções específicas para nossas próprias classes, permitindo que nossos testes reflitam melhor o modelo de domínio.

2. Classe em teste

Os casos de teste neste tutorial serão construídos em torno da classePerson:

public class Person {
    private String fullName;
    private int age;
    private List nicknames;

    public Person(String fullName, int age) {
        this.fullName = fullName;
        this.age = age;
        this.nicknames = new ArrayList<>();
    }

    public void addNickname(String nickname) {
        nicknames.add(nickname);
    }

    // getters
}

3. Classe de declaração personalizada

Escrever uma classe de asserção personalizada do AssertJ é bastante simples. All we need to do is to declare a class that extends AbstractAssert, add a required constructor, and provide custom assertion methods.

A classe de asserção deve estender a classeAbstractAssert para nos dar acesso aos métodos de asserção essenciais da API, comoisNotNulleisEqualTo.

Aqui está o esqueleto de uma classe de asserção personalizada paraPerson:

public class PersonAssert extends AbstractAssert {

    public PersonAssert(Person actual) {
        super(actual, PersonAssert.class);
    }

    // assertion methods described later
}

Devemos especificar dois argumentos de tipo ao estender a classeAbstractAssert: o primeiro é a própria classe de asserção personalizada, que é necessária para o encadeamento de métodos, e o segundo é a classe em teste.

Para fornecer um ponto de entrada para nossa classe de asserção, podemos definir um método estático que pode ser usado para iniciar uma cadeia de asserções:

public static PersonAssert assertThat(Person actual) {
    return new PersonAssert(actual);
}

A seguir, examinaremos várias asserções personalizadas incluídas na classePersonAssert.

O primeiro método verifica se o nome completo de umPerson corresponde a um argumentoString:

public PersonAssert hasFullName(String fullName) {
    isNotNull();
    if (!actual.getFullName().equals(fullName)) {
        failWithMessage("Expected person to have full name %s but was %s",
          fullName, actual.getFullName());
    }
    return this;
}

O método a seguir testa se aPerson é um adulto com base em seuage:

public PersonAssert isAdult() {
    isNotNull();
    if (actual.getAge() < 18) {
        failWithMessage("Expected person to be adult");
    }
    return this;
}

A última verifica a existência de umnickname:

public PersonAssert hasNickName(String nickName) {
    isNotNull();
    if (!actual.getNickNames().contains(nickName)) {
        failWithMessage("Expected person to have nickname %s",
          nickName);
    }
    return this;
}

Ao ter mais de uma classe de asserção personalizada, podemos agrupar todos os métodosassertThat em uma classe, fornecendo um método de fábrica estático para cada uma das classes de asserção:

public class Assertions {
    public static PersonAssert assertThat(Person actual) {
        return new PersonAssert(actual);
    }

    // static factory methods of other assertion classes
}

A classeAssertions mostrada acima é um ponto de entrada conveniente para todas as classes de asserções personalizadas.

Os métodos estáticos dessa classe têm o mesmo nome e são diferenciados um pelo outro pelo tipo de parâmetro.

4. Em ação

Os seguintes casos de teste ilustrarão os métodos de asserção personalizados que criamos na seção anterior. Observe que o métodoassertThat é importado de nossa classeAssertions personalizada, não da API AssertJ principal.

Veja como o métodohasFullName pode ser usado:

@Test
public void whenPersonNameMatches_thenCorrect() {
    Person person = new Person("John Doe", 20);
    assertThat(person)
      .hasFullName("John Doe");
}

Este é um caso de teste negativo que ilustra o métodoisAdult:

@Test
public void whenPersonAgeLessThanEighteen_thenNotAdult() {
    Person person = new Person("Jane Roe", 16);

    // assertion fails
    assertThat(person).isAdult();
}

e outro teste demonstrando o métodohasNickname:

@Test
public void whenPersonDoesNotHaveAMatchingNickname_thenIncorrect() {
    Person person = new Person("John Doe", 20);
    person.addNickname("Nick");

    // assertion will fail
    assertThat(person)
      .hasNickname("John");
}

5. Gerador de Asserções

A criação de classes de asserção personalizadas correspondentes ao modelo de objeto abre caminho para casos de teste muito legíveis.

However, if we have a lot of classes, it would be painful to manually create custom assertion classes for all of them. É aqui que o gerador de asserções AssertJ entra em jogo.

Para usar o gerador de asserções com Maven, precisamos adicionar um plugin ao arquivopom.xml:


    org.assertj
    assertj-assertions-generator-maven-plugin
    2.1.0
    
        
            com.example.testing.assertj.custom.Person
        
    

A versão mais recente doassertj-assertions-generator-maven-plugin pode ser encontradahere.

O elementoclasses no plugin acima marca as classes para as quais queremos gerar asserções. Por favor, vejathis post para outras configurações do plugin.

The AssertJ assertions generator creates assertions for each public property of the target class. O nome específico de cada método de asserção depende do tipo de campo ou propriedade. Para obter uma descrição completa do gerador de asserções, verifiquethis reference.

Execute o seguinte comando Maven no diretório base do projeto:

mvn assertj:generate-assertions

Devemos ver as classes de asserções geradas na pastatarget/generated-test-sources/assertj-assertions. For example,. A classe de ponto de entrada gerada para as asserções geradas se parece com isto:

// generated comments are stripped off for brevity

package com.example.testing.assertj.custom;

@javax.annotation.Generated(value="assertj-assertions-generator")
public class Assertions {

    @org.assertj.core.util.CheckReturnValue
    public static com.example.testing.assertj.custom.PersonAssert
      assertThat(com.example.testing.assertj.custom.Person actual) {
        return new com.example.testing.assertj.custom.PersonAssert(actual);
    }

    protected Assertions() {
        // empty
    }
}

Agora, podemos copiar os arquivos de origem gerados no diretório de teste e adicionar métodos de asserção personalizados para satisfazer nossos requisitos de teste.

Uma coisa importante a notar é que não é garantido que o código gerado seja totalmente correto. Neste ponto, o gerador não é um produto acabado e a comunidade está trabalhando nisso.

Portanto, devemos usar o gerador como uma ferramenta de apoio para facilitar nossa vida, em vez de tomá-lo como garantido.

6. Conclusão

Neste tutorial, mostramos como criar asserções personalizadas para criar código de teste legível com a biblioteca AssertJ, tanto manual quanto automaticamente.

Se temos apenas um pequeno número de classes em teste, a solução manual é suficiente; caso contrário, o gerador deve ser usado.

E, como sempre, a implementação de todos os exemplos e trechos de código pode ser encontradaover on GitHub.