Eu tenho alguns padrões diferentes que uso. Eu uso o ExpectedException
atributo na maioria das vezes quando uma exceção é esperada. Isso é suficiente para a maioria dos casos, no entanto, há alguns casos em que isso não é suficiente. A exceção pode não ser capturável - já que é lançada por um método que é invocado por reflexão - ou talvez eu apenas queira verificar se outras condições se mantêm, digamos que uma transação seja revertida ou algum valor ainda tenha sido definido. Nesses casos, eu o envolvo em um try/catch
bloco que espera a exceção exata, faz um Assert.Fail
se o código for bem-sucedido e também captura exceções genéricas para garantir que uma exceção diferente não seja lançada.
Primeiro caso:
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void MethodTest()
{
var obj = new ClassRequiringNonNullParameter( null );
}
Segundo caso:
[TestMethod]
public void MethodTest()
{
try
{
var obj = new ClassRequiringNonNullParameter( null );
Assert.Fail("An exception should have been thrown");
}
catch (ArgumentNullException ae)
{
Assert.AreEqual( "Parameter cannot be null or empty.", ae.Message );
}
catch (Exception e)
{
Assert.Fail(
string.Format( "Unexpected exception of type {0} caught: {1}",
e.GetType(), e.Message )
);
}
}
Assert.Throws
método fortemente tipado que cobre ambos os casos.Agora, 2017, você pode fazer isso mais facilmente com a nova estrutura MSTest V2 :
fonte
System.Exception
for lançado. Qualquer outro, como um,System.ArgumentException
será reprovado no teste.Assert.ThrowsException<MyException>
testará somente contra o tipo de exceção fornecido, e não qualquer um de seus tipos de exceção derivados. No meu exemplo, se o testadoSub
fosse paraThrow
aMyInheritedException
(tipo derivado da classe baseMyException
), o teste falharia .Try { SubToTest(); Assert.Fail("...") } Catch (AssertFailedException e) {throw;} Catch (MyException e) {...}
. Observe a importânciaCatch (AssertFailedException e) {throw;}
máxima de (cf. comentário de allgeek)Sou novo aqui e não tenho reputação para comentar ou votar negativamente, mas gostaria de apontar uma falha no exemplo na resposta de Andy White :
Em todas as estruturas de teste de unidade com as quais estou familiarizado,
Assert.Fail
funciona lançando uma exceção, de modo que a captura genérica na verdade mascarará a falha do teste. SeSomethingThatCausesAnException()
não jogar, oAssert.Fail
fará, mas isso nunca borbulhará para o executor de teste para indicar falha.Se você precisar capturar a exceção esperada (ou seja, para declarar certos detalhes, como a mensagem / propriedades na exceção), é importante capturar o tipo esperado específico, e não a classe de exceção base. Isso permitiria que a
Assert.Fail
exceção borbulhasse (assumindo que você não está lançando o mesmo tipo de exceção que sua estrutura de teste de unidade faz), mas ainda permitiria a validação na exceção que foi lançada por seuSomethingThatCausesAnException()
método.fonte
A partir da versão 2.5, o NUnit tem os seguintes níveis de método
Assert
para testar exceções:Assert.Throws , que testará um tipo de exceção exato:
E
Assert.Catch
, que testará para uma exceção de um determinado tipo, ou um tipo de exceção derivado deste tipo:Como um aparte, ao depurar testes de unidade que lançam exceções, você pode querer evitar que o VS interrompa a exceção .
Editar
Apenas para dar um exemplo do comentário de Mateus abaixo, o retorno do genérico
Assert.Throws
eAssert.Catch
é a exceção com o tipo da exceção, que você pode examinar para uma inspeção mais detalhada:fonte
Assert.Throws
, além disso, ele retorna a exceção para que você possa escrever mais afirmações sobre a própria exceção.Infelizmente, o MSTest AINDA só tem realmente o atributo ExpectedException (apenas mostra o quanto a MS se preocupa com o MSTest), que é muito ruim porque quebra o padrão Arrange / Act / Assert e não permite que você especifique exatamente qual linha de código você espera da exceção para ocorrer.
Quando estou usando (/ forçado por um cliente) para usar MSTest, sempre uso esta classe auxiliar:
Exemplo de uso:
fonte
Como alternativa ao uso de
ExpectedException
atributo, às vezes defino dois métodos úteis para minhas classes de teste:AssertThrowsException()
recebe um delegado e afirma que ele lança a exceção esperada com a mensagem esperada.AssertDoesNotThrowException()
pega o mesmo delegado e afirma que não lança uma exceção.Esse emparelhamento pode ser muito útil quando você deseja testar se uma exceção é lançada em um caso, mas não no outro.
Com eles, meu código de teste de unidade pode ter a seguinte aparência:
Legal e legal hein?
Os métodos My
AssertThrowsException()
eAssertDoesNotThrowException()
são definidos em uma classe base comum da seguinte maneira:fonte
Marque o teste com ExpectedExceptionAttribute (este é o termo em NUnit ou MSTest; usuários de outras estruturas de teste de unidade podem precisar traduzir).
fonte
Com a maioria das estruturas de teste de unidade .net, você pode colocar um atributo [ExpectedException] no método de teste. No entanto, isso não pode dizer que a exceção aconteceu no ponto que você esperava. É aí que a xunit.net pode ajudar.
Com o xunit você tem Assert.Throws, então você pode fazer coisas assim:
[Fato] é o equivalente xunit de [TestMethod]
fonte
Sugira o uso da sintaxe de delegado limpo do NUnit .
Exemplo para teste
ArgumentNullExeption
:fonte