Pregunta ¿Cómo uso Assert para verificar que se haya lanzado una excepción?


¿Cómo uso Assert (u otra clase de prueba?) Para verificar que se haya lanzado una excepción.


671
2018-06-01 05:01


origen


Respuestas:


Para "Visual Studio Team Test", parece que aplica el atributo ExpectedException al método de la prueba.

Muestra de la documentación aquí: Una prueba de unidad Tutorial con prueba de equipo de Visual Studio

[TestMethod]
[ExpectedException(typeof(ArgumentException),
    "A userId of null was inappropriately allowed.")]
public void NullUserIdInConstructor()
{
   LogonInfo logonInfo = new LogonInfo(null, "P@ss0word");
}

804
2018-06-01 05:09



Por lo general, su marco de prueba tendrá una respuesta para esto. Pero si no es lo suficientemente flexible, siempre puedes hacer esto:

try {
    somethingThatShouldThrowAnException();
    Assert.Fail(); // If it gets to this line, no exception was thrown
} catch (GoodException) { }

Como señala @Jonas, esto NO funciona para atrapar una excepción base:

try {
    somethingThatShouldThrowAnException();
    Assert.Fail(); // raises AssertionException
} catch (Exception) {
    // Catches the assertion exception, and the test passes
}

Si absolutamente debe atrapar Exception, necesita volver a lanzar el Assert.Fail (). Pero en realidad, este es un signo de que no debes escribir esto a mano; verifique las opciones en su marco de prueba o vea si puede lanzar una excepción más significativa para probar.

catch (AssertionException) { throw; }

Debería ser capaz de adaptar este enfoque a lo que quiera, incluso especificar qué tipos de excepciones atrapar. Si solo espera ciertos tipos, termine el catch bloquea con:

} catch (GoodException) {
} catch (Exception) {
    // not the right kind of exception
    Assert.Fail();
}

222
2018-06-01 05:06



Mi método preferido para implementar esto es escribir un método llamado Throws, y usarlo como cualquier otro método de Assert. Desafortunadamente, .NET no le permite escribir un método de extensión estático, por lo que no puede usar este método como si realmente perteneciera a la construcción en la clase Assert; acaba de hacer otro llamado MyAssert o algo similar. La clase se ve así:

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace YourProject.Tests
{
    public static class MyAssert
    {
        public static void Throws<T>( Action func ) where T : Exception
        {
            var exceptionThrown = false;
            try
            {
                func.Invoke();
            }
            catch ( T )
            {
                exceptionThrown = true;
            }

            if ( !exceptionThrown )
            {
                throw new AssertFailedException(
                    String.Format("An exception of type {0} was expected, but not thrown", typeof(T))
                    );
            }
        }
    }
}

Eso significa que su prueba de unidad se ve así:

[TestMethod()]
public void ExceptionTest()
{
    String testStr = null;
    MyAssert.Throws<NullReferenceException>(() => testStr.ToUpper());
}

Que se ve y se comporta mucho más como el resto de las sintaxis de prueba de su unidad.


98
2018-04-12 11:20



Si está utilizando MSTest, que originalmente no tenía una ExpectedException atributo, podrías hacer esto:

try 
{
    SomeExceptionThrowingMethod()
    Assert.Fail("no exception thrown");
}
catch (Exception ex)
{
    Assert.IsTrue(ex is SpecificExceptionType);
}

56
2018-06-01 05:10



Tenga cuidado con el uso de ExpectedException, ya que puede dar lugar a varias trampas como se demuestra aquí:

http://geekswithblogs.net/sdorman/archive/2009/01/17/unit-testing-and-expected-exceptions.aspx

Y aquí:

http://xunit.github.io/docs/comparisons.html

Si necesita probar excepciones, hay maneras menos mal vistas. Puede usar el método try {act / fail} catch {assert}, que puede ser útil para frameworks que no tienen soporte directo para pruebas de excepción que no sean ExpectedException.

Una mejor alternativa es usar xUnit.NET, que es un marco de prueba de unidades muy moderno, prospectivo y extensible que ha aprendido de todos los demás errores y ha mejorado. Una de esas mejoras es Assert.Throws, que proporciona una sintaxis mucho mejor para hacer valer excepciones.

Puedes encontrar xUnit.NET en github: http://xunit.github.io/


36
2018-06-01 05:22



si usa NUNIT, puede hacer algo como esto:

Assert.Throws<ExpectedException>(() => methodToTest());


También es posible almacenar la excepción lanzada para validarla aún más:

ExpectedException ex = Assert.Throws<ExpectedException>(() => methodToTest());
Assert.AreEqual( "Expected message text.", ex.Message );
Assert.AreEqual( 5, ex.SomeNumber);

Ver: http://nunit.org/docs/2.5/exceptionAsserts.html


34
2017-12-04 11:02



En un proyecto en el que estoy trabajando tenemos otra solución para hacer esto.

Primero, no me gusta el ExpectedExceptionAttribute porque toma en consideración qué llamada de método causó la excepción.

Lo hago con un método de ayuda en su lugar.

Prueba

[TestMethod]
public void AccountRepository_ThrowsExceptionIfFileisCorrupt()
{
     var file = File.Create("Accounts.bin");
     file.WriteByte(1);
     file.Close();

     IAccountRepository repo = new FileAccountRepository();
     TestHelpers.AssertThrows<SerializationException>(()=>repo.GetAll());            
}

HelperMethod

public static TException AssertThrows<TException>(Action action) where TException : Exception
    {
        try
        {
            action();
        }
        catch (TException ex)
        {
            return ex;
        }
        Assert.Fail("Expected exception was not thrown");

        return null;
    }

Limpio, ¿no?)


24
2017-10-01 21:13



Es un atributo en el método de prueba ... no usa Assert. Se ve como esto:

[ExpectedException(typeof(ExceptionType))]
public void YourMethod_should_throw_exception()

15
2018-06-01 05:09



Puede descargar un paquete de Nuget usando: PM> Install-Package MSTestExtensions eso agrega Assert.Throws () sintaxis en el estilo de nUnit / xUnit to MsTest.

Instrucciones de alto nivel: descargue el ensamblado y herede de Prueba base y puedes usar el Assert.Throws () sintaxis.

El método principal para la implementación de Throws es el siguiente:

public static void Throws<T>(Action task, string expectedMessage, ExceptionMessageCompareOptions options) where T : Exception
{
    try
    {
        task();
    }
    catch (Exception ex)
    {
        AssertExceptionType<T>(ex);
        AssertExceptionMessage(ex, expectedMessage, options);
        return;
    }

    if (typeof(T).Equals(new Exception().GetType()))
    {
        Assert.Fail("Expected exception but no exception was thrown.");
    }
    else
    {
        Assert.Fail(string.Format("Expected exception of type {0} but no exception was thrown.", typeof(T)));
    }
}

Divulgación: armé este paquete.

Más información: http://www.bradoncode.com/blog/2012/01/asserting-exceptions-in-mstest-with.html


13
2018-04-07 23:11