Utilizzare il metodo NUnit Assert.Throws o l'attributo ExpectedException?


146

Ho scoperto che questi sembrano essere i due modi principali di testare le eccezioni:

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

[ExpectedException(typeof(Exception))]

Quale di questi sarebbe il migliore? Uno offre vantaggi rispetto all'altro? O è semplicemente una questione di preferenze personali?


3
Una terza opzione è lo stile fluente:Assert.That(() => MethodThatThrows(), Throws.Exception)
Jack Ukleja,

1
NUnit versione 3 e successive non supporta più l' ExpectedExceptionattributo, quindi per la versione 3+ Assert.Throwsè rilevante solo la variante.
joanlofe,

Perché è così? Che Nunit3 ha deciso di abbandonare quel supporto? Cercava su Google e non riuscivo a trovare spiegazioni per questo ... JUnit supporta ancora in questo modo, no?
ahaaman,

Risposte:


92

Il primo consente di testare più di un'eccezione, con più chiamate:

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

Il secondo consente solo di verificare un'eccezione per funzione di test.


25
Un test dovrebbe testare solo un bit distinto di logica, quindi testare due errori nello stesso test unitario non sarebbe considerato una cattiva pratica?
SamuelDavis,

5
@SamuelDavis - in generale non vorrai testare diversi casi nello stesso test. Tuttavia, potrebbe esserci un caso d'uso per più Assert.Throws.
chue x

3
Ad ogni modo, qui ottieni l'eccezione come parametro, che ti consente di affermare i dettagli nell'eccezione. Inoltre, l'utilizzo di "Eccezione prevista" non protegge l'utente per lo stesso tipo di eccezione generato in un'altra chiamata di metodo. Qui, scegli come target il metodo esatto e non l'intero test. Anche se il tuo test dovrebbe chiamare pochissimo codice, non sei mai troppo sicuro. Soprattutto quando il codice diventa complesso e / o eccezione troppo generica. Roba come "ArgumentNullExceptions" può essere lanciata molto e, ad esempio, si perderebbe facilmente usando ExpectedException. Assert.Throws non lo mancherebbe.
Gil Sand,

254

La differenza principale è:

ExpectedException()l'attributo fa passare il test se si verifica un'eccezione in qualsiasi punto del metodo di test.
L'uso di Assert.Throws()consente di specificare la exactposizione del codice in cui è prevista un'eccezione.

NUnit 3.0 elimina ExpectedExceptioncompletamente il supporto ufficiale .

Quindi, preferisco decisamente usare il Assert.Throws()metodo piuttosto che l' ExpectedException()attributo.


7
Questa è di gran lunga la risposta corretta. Per inciso, Assert.Throws () restituisce anche l'eccezione, che può consentire un'ulteriore ispezione delle proprietà dell'eccezione, se importanti.
perfezionista

1
Infine, rispondi perché non riesco a far funzionare ExpectedException .. con la versione 3.
JanT

2
Ecco il link github.com/nunit/docs/wiki/Breaking-Changes - ExpectedExceptionAttribute non è più supportato.
Anton Lyhin,

Per cambiarlo per funzionare con NUnit 3.0, modificalo come segue
Andrei Krasutski,

38

Preferisco assert.throws poiché mi consente di verificare e affermare altre condizioni dopo che è stata generata l'eccezione.

    [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");

    }

Questa è una delle risposte migliori, è abbastanza comune che tu voglia verificare che qualcosa sia entrato in uno stato errato dopo che l'eccezione è stata lanciata.
Rhys Bevilaqua,

11

Puoi anche digitare forte l'errore che ti aspetti (come la vecchia versione di attrib).

Assert.Throws<System.InvalidOperationException>(() => breakingAction())

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.