2012-03-27 10 views
12

Tengo una clase que crea un archivo.Usando NUnit para probar cualquier tipo de excepción

Ahora estoy haciendo pruebas de integración para asegurarme de que la clase está bien.

Estoy pasando nombres inválidos de directorios y archivos para asegurarme de que se lanzan las excepciones.

En mis pruebas son que estoy utilizando:

[Test] 
public void CreateFile_InvalidFileName_ThrowsException() 
{ 
    //Arrange 
    var logger = SetupLogger("?\\"); 

    //Act 

    //Assert 
    Assert.Throws<Exception>(()=> logger.CreateFile()); 
} 

Sin embargo, en este escenario la prueba está fallando como un ArgumentException es lanzada. Pensé que al agregar Just Exception pasaría.

¿Hay alguna manera de hacer que esto pase usando Exception?

+1

Una razón por la que sería una buena idea para comprobar si una excepción específica es que los clientes del registrador probablemente va a querer evitar tener que coger la base de clase 'Exception', y por lo tanto se basará en una excepción en particular ser arrojado, entonces eso es lo que debes probar. – Ergwun

Respuesta

21

La ayuda para Assert.Throws<> afirma que "Verifica un delegado lanza un tipo particular de excepción cuando se le llama"

probar la versión Assert.That ya que la captura de cualquier Exception:

private class Thrower 
{ 
    public void ThrowAE() { throw new ArgumentException(); } 
} 

[Test] 
public void ThrowETest() 
{ 
    var t = new Thrower(); 
    Assert.That(() => t.ThrowAE(), Throws.Exception); 
} 
+0

+1 ya que esto realmente responde la pregunta, pero no ignore los buenos consejos en otras respuestas para probar excepciones específicas. – Ergwun

+0

Si necesita verificar las propiedades de excepción o escribir más tarde, puede hacer: 'var ex = Assert.Throws (Is.AssignableTo (typeof (Exception)),() => DoSomething());' –

1

Puede etiquetar su método de prueba con el atributo ExpectedException. Eso debería funcionar.

[ExpectedException(typeof(Exception))] 
    public void TestException() 
    { 

    } 
+0

Después de leer el libro de Roy Osherove trato de no utilizar los atributos – Jon

+0

Interesante, he leído las pruebas unitarias pragmáticas y me alientan a usar los atributos (y personalmente los uso también). ¿Cuidar para explicar por qué no usarlos? Estaría contento con un enlace o blog. – Alex

+0

No puedo encontrarlo en el libro ahora, así que tal vez fue su curso de TDD http://tekpub.com/productions/tdd – Jon

2

Sus excepciones deben ser determinista, y usted debe ser capaz de escribir casos de prueba que establecen las condiciones bajo las cuales se produce una excepción específica, y se debe probar para esa excepción específica.

Por lo tanto, la prueba debe ser reescrito como

CreateFile_InvalidFileName_ThrowsArgumentException 

y

Assert.Throws<ArgumentException>(() => logger.CreateFile()); 

Editar:

Por cierto, creo que el constructor debe estar detectando nombres de los archivos no válidos y tirar allí . Y entonces debería ser un contrato para el constructor que el nombre del archivo sea válido.

+0

Acepto, pero hay muchas cosas extrañas en las que pensar y muchas excepciones que probablemente se generen al crear archivos. Me pregunto si ya hay pruebas de integración previamente escritas para este tipo de escenario – Jon

+0

+1 Como aunque no responda la pregunta, estoy de acuerdo con este consejo. Los tipos de excepción que arroja su clase forman parte de su API pública, por lo que deben probarse. – Ergwun

+0

@Jon, estuvo de acuerdo en que es un dolor con la cantidad de diferentes tipos de excepciones que pueden arrojarse con ciertos métodos en el BCL. Si su clase de registrador quería ser más amigable, podría capturar esas excepciones y lanzar una única excepción (o al menos menos excepciones) envolviendo el original como una excepción interna. Entonces, querrá probar esa excepción explícitamente en sus pruebas automatizadas. – Ergwun

1

En general, solo debe probar excepciones específicas para asegurarse de que su código responde correctamente a los diferentes errores.

Si realmente necesita permitir cualquier excepción por el bien de su prueba, solo use un bloque de prueba/captura estándar y asegura el éxito/falla.

1

Escriba su propio método y usar eso para validación.

/// <summary> 
    /// Throwses the specified action. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="action">The action.</param> 
    /// <returns></returns> 
    public static T Throws<T>(Action action) where T : Exception 
    { 
     try 
     { 
      action(); 
     } 
     catch (T ex) 
     { 
      return ex; 
     } 

     Assert.Fail("Expected exception of type {0}.", typeof(T)); 
     return null; 
    } 
4

Para NUnit 2,5 y por encima de

// Allow both ApplicationException and any derived type 
Assert.Catch<ApplicationException>(() => logger.CreateFile()); 

// Allow any kind of exception 
Assert.Catch(() => logger.CreateFile()); 
+0

'Assert.Catch ' resuelve la pregunta formulada al punto * y *, como 'Assert.Throw ', permite obtener la excepción como resultado: 'var ex = Assert.Catch (() => ..); AssertMoreOnException (ex); '. – user2864740

0

Throws.InstanceOf() permite pasar un tipo de excepción base, en lugar de un tipo derivado más específico.

[Test] 
public void CreateFile_InvalidFileName_ThrowsException() 
{ 
    //Arrange 
    var logger = SetupLogger("?\\"); 

    //Act 

    //Assert 
    Assert.That(() => logger.CreateFile(), Throws.InstanceOf<Exception>()); 
} 
Cuestiones relacionadas