Você está abordando isso da maneira errada. Apenas teste sua funcionalidade: se uma exceção for lançada, o teste falhará automaticamente. Se nenhuma exceção for lançada, todos os seus testes ficarão verdes.
Percebi que essa pergunta gera interesse de tempos em tempos, por isso vou expandir um pouco.
Antecedentes do teste de unidade
Quando você faz testes de unidade, é importante definir para si mesmo o que você considera uma unidade de trabalho. Basicamente: uma extração da sua base de código que pode ou não incluir vários métodos ou classes que representa uma única peça de funcionalidade.
Ou, conforme definido em The art of Unit Testing, 2ª edição de Roy Osherove , página 11:
Um teste de unidade é um trecho de código automatizado que chama a unidade de trabalho que está sendo testada e, em seguida, verifica algumas suposições sobre um único resultado final dessa unidade. Um teste de unidade é quase sempre escrito usando uma estrutura de teste de unidade. Pode ser escrito facilmente e é executado rapidamente. É confiável, legível e sustentável. É consistente em seus resultados, desde que o código de produção não tenha sido alterado.
O que é importante perceber é que uma unidade de trabalho geralmente não é apenas um método, mas no nível muito básico é um método e depois disso é encapsulado por outra unidade de obras.
Idealmente, você deve ter um método de teste para cada unidade de trabalho separada, para poder sempre ver imediatamente onde as coisas estão dando errado. Neste exemplo, existe um método básico chamado getUserById()
que retornará um usuário e há um total de 3 unidades de obras.
A primeira unidade de trabalho deve testar se um usuário válido está ou não sendo retornado no caso de entrada válida e inválida.
Quaisquer exceções que estão sendo lançadas pela fonte de dados devem ser tratadas aqui: se nenhum usuário estiver presente, deve haver um teste que demonstre que uma exceção será lançada quando o usuário não puder ser encontrado. Uma amostra disso pode ser a IllegalArgumentException
que é capturada com a @Test(expected = IllegalArgumentException.class)
anotação.
Depois de ter tratado todos os seus casos de uso para esta unidade básica de trabalho, você sobe de nível. Aqui você faz exatamente o mesmo, mas apenas lida com as exceções que vêm do nível logo abaixo do atual. Isso mantém seu código de teste bem estruturado e permite que você percorra rapidamente a arquitetura para descobrir onde as coisas dão errado, em vez de ter que pular por todo o lugar.
Manipulação de entrada válida e defeituosa de um teste
Neste ponto, deve ficar claro como vamos lidar com essas exceções. Existem 2 tipos de entrada: entrada válida e entrada com defeito (a entrada é válida no sentido estrito, mas não está correta).
Quando você trabalha com entrada válida, está definindo a expectativa implícita de que qualquer teste que você escrever funcionará.
Tal chamada de método pode ficar assim: existingUserById_ShouldReturn_UserObject
. Se esse método falhar (por exemplo: uma exceção for lançada), você saberá que algo deu errado e poderá começar a cavar.
Adicionando outro teste ( nonExistingUserById_ShouldThrow_IllegalArgumentException
) que usa a entrada defeituosa e espera uma exceção, você pode ver se o seu método faz o que é suposto fazer com a entrada incorreta.
TL; DR
Você estava tentando fazer duas coisas em seu teste: verifique se há entradas válidas e com defeito. Dividindo isso em dois métodos, cada um fazendo uma coisa, você terá testes muito mais claros e uma visão geral muito melhor de onde as coisas dão errado.
Ao manter em mente a unidade de trabalho em camadas, você também pode reduzir a quantidade de testes necessários para uma camada que é mais alta na hierarquia, porque não é necessário contabilizar tudo o que pode ter dado errado nas camadas inferiores: o as camadas abaixo da atual são uma garantia virtual de que suas dependências funcionam e, se algo der errado, está na sua camada atual (supondo que as camadas inferiores não causem erros).