Criando Soft Assertions com AssertJ (assertSoftly)
Ao concluirmos esta aula, nós:
- Compreenderemos quando faz sentido escrever múltiplas asserções dentro do mesmo método de teste.
- Saberemos como agrupar múltiplas asserções em um único método de teste utilizando as Soft Assertions do AssertJ (
SoftAssertionseSoftAssertions.assertSoftly).
O Que É uma Soft Assertion?
Muitos desenvolvedores acreditam que cada método de teste deve conter apenas uma única asserção. A razão para isso é que, se um método de teste possuir múltiplas asserções tradicionais (hard assertions) e uma delas falhar, não saberemos o resultado das asserções que deveriam ser executadas após a asserção que falhou — pois a primeira falha lança imediatamente um AssertionError e aborta o método.
Essa é uma boa regra geral, mas segui-la cegamente pode causar outro problema sério. Suponha que queiramos escrever testes para um método que transforma um objeto em outro objeto diferente.
Se seguirmos a regra de “uma asserção por teste” à risca, teremos que escrever um método de teste separado para cada propriedade do objeto retornado. Por exemplo, se precisarmos escrever asserções para a classe TaskDTO, o código-fonte da nossa classe de teste ficaria assim:
|
|
Há um problema evidente com essa classe de teste:
Ela é difícil de ler devido à enorme quantidade de código repetitivo (boilerplate) necessário para declarar nove métodos de teste separados para verificar o resultado de uma única operação lógica.
Em outras palavras, se precisarmos verificar o estado de um objeto que contém múltiplas propriedades independentes, é muito melhor colocar todas as asserções dentro de um único método de teste. Contudo, se fizermos isso usando asserções normais (Assertions.assertThat()), voltaremos ao problema original: se a primeira asserção falhar, o teste será interrompido e não saberemos se as demais propriedades estavam corretas ou incorretas.
Felizmente para nós, podemos resolver esse problema utilizando Soft Assertions. Quando usamos soft assertions, o AssertJ coleta todas as falhas de asserção que ocorrem dentro do método de teste sem interromper a execução imediatamente e relata todas as falhas juntas ao final do bloco.
Vamos descobrir como podemos escrever soft assertions com o AssertJ!
Escrevendo Soft Assertions com AssertJ
Ao escrevermos soft assertions com o AssertJ, utilizamos a classe org.assertj.core.api.SoftAssertions. Em vez de usar o método estático Assertions.assertThat(), invocamos os métodos assertThat() de uma instância de SoftAssertions para especificar nossas expectativas.
No AssertJ moderno com Kotlin, existem duas maneiras principais de utilizar SoftAssertions:
- Abordagem com instância explícita e
assertAll(): Criamos uma instância deSoftAssertions, registramos as asserções e chamamossoftAssertions.assertAll()no final. - Abordagem funcional com
SoftAssertions.assertSoftly { ... }(Recomendada em Kotlin): Passamos um bloco lambda paraassertSoftly, e o próprio AssertJ invocaassertAll()automaticamente ao final do bloco (sem o risco de esquecermos a chamada final).
Vamos primeiro ver passo a passo como funciona a abordagem explícita para entendermos o mecanismo interno, e em seguida a forma idiomática em Kotlin com assertSoftly.
Passo a Passo com SoftAssertions e assertAll()
Para escrever um método de teste que verifica se as informações de um objeto Person estão corretas usando uma instância de SoftAssertions, seguimos estes passos:
- Criamos um novo objeto
Person. - Criamos uma nova instância de
SoftAssertions. - Escrevemos as asserções que verificam se o primeiro nome (
firstName) e o sobrenome (lastName) estão corretos, utilizando os métodos da instânciaSoftAssertions. - Invocamos o método
assertAll()da classeSoftAssertionspara instruir o AssertJ a avaliar todas as asserções coletadas.
Vamos implementar esse teste na prática:
Passo 1: Criar o objeto Person
|
|
Passo 2: Criar uma instância de SoftAssertions
|
|
Passo 3: Especificar as asserções para firstName e lastName
|
|
Passo 4: Invocar assertAll()
|
|
[!WARNING] Atenção ao
assertAll()! Quando você instanciaSoftAssertions()manualmente, não pode esquecer de chamarsoftAssertions.assertAll()na última linha do método de teste! Se você esquecer essa chamada, nenhuma asserção será efetivamente verificada e o seu teste passará com falso positivo mesmo que todas as propriedades estejam erradas.
A Forma Idiomática em Kotlin: SoftAssertions.assertSoftly
Para eliminar completamente o risco de esquecer a chamada assertAll(), o AssertJ oferece o método estático SoftAssertions.assertSoftly. Em Kotlin, podemos combiná-lo perfeitamente com blocos lambda:
|
|
Quando o bloco lambda passado para assertSoftly termina de executar, o próprio AssertJ chama assertAll() automaticamente por baixo dos panos. Se tanto firstName quanto lastName estiverem incorretos, o relatório de falha exibirá ambas as mensagens de erro simultaneamente!
Resumo
Nesta aula, aprendemos que:
- Se precisarmos verificar o estado de um objeto que contém múltiplas propriedades correlacionadas, devemos agrupar todas as asserções desse objeto dentro de um único método de teste em vez de espalhá-las em dezenas de testes repetitivos.
- Se colocarmos múltiplas asserções no mesmo método de teste, devemos implementá-las como Soft Assertions para garantir que todas sejam avaliadas mesmo quando uma delas falha.
- Se instanciarmos
SoftAssertions()manualmente, jamais devemos esquecer de invocar o métodoassertAll()ao final do método de teste — ou, melhor ainda, devemos preferirSoftAssertions.assertSoftly { softly -> ... }em Kotlin para que a verificação final ocorra automaticamente.