Capturando exceções no MSTest: guia completo sobre Assert.ThrowsException

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Como capturar uma exceção no MSTest e não enlouquecer?

\n\n

Você está escrevendo testes unitários em C# e de repente percebe: seu método deve lançar uma exceção em uma determinada situação. Como verificar isso? Se você pesquisou "How do I use Assert to verify that an exception has been thrown with MSTest", não está sozinho — esta é uma das perguntas mais populares no Stack Overflow. E hoje vamos resolvê-la de uma vez por todas.

\n\n

Neste artigo, mostrarei a você todas as formas de verificar exceções no MSTest: desde o atributo clássico até o moderno Assert.ThrowsException. Você aprenderá a escrever testes limpos e confiáveis que não falharão no momento mais inoportuno. Vamos lá!

\n\n

Por que a verificação de exceções é importante?

\n\n

Imagine: você tem um método Divide(int a, int b). Se b = 0, ele deve lançar DivideByZeroException. Sem um teste, você só descobrirá isso quando a aplicação cair em produção. Um teste unitário com verificação de exceção é o seu cabo de segurança.

\n\n

No MSTest (framework de teste de unidade da Microsoft), existem várias abordagens. Vamos analisar cada uma, mas começaremos pela mais moderna e recomendada.

\n\n

Método 1: Assert.ThrowsException (O mais correto)

\n\n

A partir do MSTest V2 (versão 2.x), temos o método embutido Assert.ThrowsException<T>. É elegante, legível e flexível. A sintaxe é simples:

\n\n
[TestMethod]\npublic void Divide_ByZero_ThrowsDivideByZeroException()\n{\n    // Arrange\n    var calculator = new Calculator();\n\n    // Act & Assert\n    Assert.ThrowsException<DivideByZeroException>(() => calculator.Divide(10, 0));\n}
\n\n

O que acontece aqui? Passamos uma expressão lambda com a chamada do método. O MSTest a executa dentro de um bloco try-catch. Se a exceção NÃO for lançada — o teste falha. Se for lançada uma exceção de outro tipo — também falha. Apenas a exceção esperada resulta em sucesso.

\n\n

Exemplo avançado: verificar a mensagem da exceção

\n\n

Às vezes, é necessário garantir não apenas o tipo da exceção, mas também sua mensagem. Para isso, use a sobrecarga com o parâmetro message ou verifique as propriedades do objeto de exceção:

\n\n
[TestMethod]\npublic void GetUserById_InvalidId_ThrowsWithCorrectMessage()\n{\n    // Arrange\n    var service = new UserService();\n\n    // Act\n    var exception = Assert.ThrowsException<ArgumentException>(() => service.GetUserById(-1));\n\n    // Assert adicional\n    Assert.AreEqual("Id must be positive", exception.Message);\n}
\n\n

Observe: Assert.ThrowsException retorna o objeto de exceção! Isso permite verificar qualquer uma de suas propriedades: InnerException, Data, StackTrace (embora este último geralmente não seja verificado).

\n\n

Método 2: Atributo [ExpectedException] (Obsoleto, mas ainda em uso)

\n\n

Antigamente (no MSTest V1), usava-se um atributo sobre o próprio método de teste. Ficava assim:

\n\n
[TestMethod]\n[ExpectedException(typeof(DivideByZeroException))]\npublic void Divide_ByZero_ThrowsDivideByZeroException_OldWay()\n{\n    var calculator = new Calculator();\n    calculator.Divide(10, 0);\n}
\n\n

Parece conveniente? Mas existem três problemas:

\n
    \n
  • Não é possível verificar a mensagem da exceção. Você não sabe se a exceção correta foi lançada.
  • \n
  • Qualquer exceção desse tipo é sucesso. Mesmo que tenha sido lançada de outra linha de código (por exemplo, no Arrange).
  • \n
  • Não é possível executar código após a exceção. O método de teste é interrompido imediatamente.
  • \n
\n\n

Portanto, em novos projetos, use Assert.ThrowsException. O atributo [ExpectedException] está marcado como deprecated (obsoleto) e pode ser removido em versões futuras.

\n\n

Método 3: Try-catch manual (Para radicais)

\n\n

Às vezes (muito raramente) você pr

Blogs

Book Recommendations