2012-03-27 2 views
12

Ho una classe che crea un file.Utilizzo di NUnit per verificare qualsiasi tipo di eccezione

Ora sto facendo test di integrazione per assicurarmi che la classe sia ok.

Sto passando nomi di directory e file non validi per accertarmi che vengano emesse eccezioni.

Nel mio test sono sto usando:

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

    //Act 

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

Tuttavia, in questo scenario il test sta fallendo come un ArgumentException viene generata. Ho pensato aggiungendo solo l'eccezione che sarebbe passata.

C'è un modo per rendere questo passaggio usando solo Eccezione?

+1

Uno dei motivi per cui sarebbe una buona idea per testare per una deroga specifica è che i clienti del registratore probabilmente vorranno evitare di dover prendere la base di classe 'Exception', e sarà quindi contare su una particolare eccezione essere gettato, quindi è quello che dovresti provare. – Ergwun

risposta

21

L'aiuto per Assert.Throws<> afferma che "Verifica un delegato getta un particolare tipo di eccezione quando viene chiamato"

provare la versione Assert.That come si cattura qualsiasi 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 in quanto risponde effettivamente alla domanda, ma non ignorare il buon consiglio in altre risposte per verificare eccezioni specifiche. – Ergwun

+0

Se è necessario controllare le proprietà di eccezione o digitare in un secondo momento è possibile: 'var ex = Assert.Throws (Is.AssignableTo (typeof (Exception)),() => DoSomething());' –

1

È possibile contrassegnare il metodo di prova con l'attributo ExpectedException. Questo dovrebbe funzionare

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

    } 
+0

Dopo aver letto il libro di Roy Osherove, cerco di non usare gli attributi – Jon

+0

Interessante, ho letto i test pragmatici delle unità e incoraggiano l'uso degli attributi (e li uso personalmente anch'io). Cura di elaborare perché non usarli? Sarei felice di un link o di un blog. – Alex

+0

Non riesco a trovarlo nel libro ora, quindi forse era il suo corso TDD http://tekpub.com/productions/tdd – Jon

2

vostri eccezioni dovrebbero essere deterministico, e si dovrebbe essere in grado di scrivere i casi di test che si insediano condizioni in cui verrà generata un'eccezione specifica, e si dovrebbe provare per quella specifica eccezione.

Così, il test deve essere riscritta come

CreateFile_InvalidFileName_ThrowsArgumentException 

e

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

Edit:

A proposito, credo che il vostro costruttore dovrebbe essere rilevando i nomi di file non validi e gettando lì . E quindi dovrebbe essere un contratto per il costruttore che il nome del file sia valido.

+0

Sono d'accordo, ma ci sono molte cose strane a cui pensare e molte eccezioni che potrebbero essere generate durante la creazione di file. Mi chiedo se ci siano già test di integrazione pre-scritti per questo tipo di scenario – Jon

+0

+1 Come anche se non rispondi alla domanda, sono d'accordo con questo consiglio. I tipi di eccezioni utilizzati dalla tua classe fanno parte della sua API pubblica, e quindi dovrebbero essere testati. – Ergwun

+0

@Jon, concordato che è un problema con il numero di diversi tipi di eccezioni che possono essere lanciati da alcuni metodi nel BCL. Se la tua classe di logger voleva essere più amichevole, poteva catturare quelle eccezioni e lanciare una singola eccezione (o almeno meno eccezioni) avvolgendo l'originale come eccezione interna. Dovresti quindi testare esplicitamente tale eccezione nei tuoi test automatici. – Ergwun

1

In generale, è necessario verificare solo eccezioni specifiche per assicurarsi che il codice risponda correttamente a diversi errori.

Se è davvero necessario consentire qualsiasi eccezione per il proprio test, utilizzare solo un blocco try/catch standard e gli insuccessi Success/Failure normali.

1

Scrivi la tua metodo e usalo per la convalida.

/// <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

Per NUnit 2.5 e sopra

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

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

'Assert.Catch ' risolve la domanda posta a punto * e *, come "Assert.Throw ", consente di ottenere l'Eccezione come risultato: 'var ex = Assert.Catch (() => ..); AssertMoreOnException (ex); '. – user2864740

0

Throws.InstanceOf() permette di passare un tipo di eccezione base, invece di un tipo derivato più specifico.

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

    //Act 

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