¿Usar el método NUnit Assert.Throws o el atributo ExpectedException?

146

He descubierto que estas parecen ser las dos formas principales de probar excepciones:

Assert.Throws<Exception>(()=>MethodThatThrows());

[ExpectedException(typeof(Exception))]

¿Cuál de estos sería el mejor? ¿Uno ofrece ventajas sobre el otro? ¿O es simplemente una cuestión de preferencia personal?

SamuelDavis
fuente
3
Una tercera opción es el estilo fluido:Assert.That(() => MethodThatThrows(), Throws.Exception)
Jack Ukleja
1
NUnit versión 3 y posteriores ya no son compatibles con el ExpectedExceptionatributo, por lo que para la versión 3+ solo la Assert.Throwsvariante es relevante.
joanlofe
¿Por que es esto entonces? ¿Que Nunit3 decidió abandonar ese soporte? Estaba buscando en Google y no pude encontrar una explicación para ello ... JUnit todavía lo admite de esta manera, ¿no?
ahaaman

Respuestas:

92

El primero le permite probar más de una excepción, con múltiples llamadas:

Assert.Throws(()=>MethodThatThrows());
Assert.Throws(()=>Method2ThatThrows());

El segundo solo le permite probar una excepción por función de prueba.

chue x
fuente
25
Una prueba solo debe probar un bit distinto de lógica, por lo que ¿no se consideraría una mala práctica probar dos errores en la misma prueba unitaria?
SamuelDavis
55
@SamuelDavis: en general, no querría probar diferentes casos en la misma prueba. Sin embargo, puede haber algún caso de uso para múltiples Assert.Throws.
chue x
3
De cualquier manera, aquí obtienes la excepción como un parámetro, que te permite afirmar detalles en la excepción. Además, el uso de "Excepción esperada" no lo protege para el mismo tipo de excepción que se genera en otra llamada a método. Aquí, apunta al método exacto y no a toda la prueba. Aunque su prueba debe llamar a muy poco código, nunca es demasiado seguro. Especialmente cuando el código se vuelve complejo y / o la excepción es demasiado genérica. Cosas como "ArgumentNullExceptions" se pueden arrojar mucho y, por ejemplo, se perderían fácilmente con la ExpectedException. Afirmar: los tiros no se lo perderían.
Gil Sand
254

La principal diferencia es:

ExpectedException()El atributo hace pasar la prueba si se produce una excepción en cualquier lugar del método de prueba.
El uso de Assert.Throws()permite especificar el exactlugar del código donde se espera una excepción.

NUnit 3.0 deja de ofrecer soporte oficial por ExpectedExceptioncompleto.

Entonces, definitivamente prefiero usar el Assert.Throws()método en lugar del ExpectedException()atributo.

Alexander Stepaniuk
fuente
77
Esta es, con mucho, la respuesta correcta. Por cierto, Assert.Throws () también devuelve la excepción, que puede permitir una inspección adicional de las propiedades de la excepción, si son importantes para usted.
perfeccionista
1
Finalmente responda por qué no puedo hacer que ExpectedException funcione ... con la versión 3.
JanT
2
Aquí está el enlace github.com/nunit/docs/wiki/Breaking-Changes - ExpectedExceptionAttribute ya no es compatible.
Anton Lyhin
Para cambiar esto para que funcione bajo NUnit 3.0, cámbielo a lo siguiente
Andrei Krasutski,
38

Prefiero afirmar. Arroja ya que me permite verificar y afirmar otras condiciones después de que se lanza la excepción.

    [Test]
    [Category("Slow")]
    public void IsValidLogFileName_nullFileName_ThrowsExcpetion()
    {
        // the exception we expect thrown from the IsValidFileName method
        var ex = Assert.Throws<ArgumentNullException>(() => a.IsValidLogFileName(""));

        // now we can test the exception itself
        Assert.That(ex.Message == "Blah");

    }
Mike Parkhill
fuente
Esta es una de las mejores respuestas, es bastante común que desee verificar que algo ha entrado en un estado de error después de que se lanza la excepción.
Rhys Bevilaqua
11

También puede escribir con fuerza el error que espera (como la versión antigua de Attrib).

Assert.Throws<System.InvalidOperationException>(() => breakingAction())
Reverendo Sfinks
fuente