Utilisez la méthode NUnit Assert.Throws ou l'attribut ExpectedException?


146

J'ai découvert que ceux-ci semblent être les deux principaux moyens de tester les exceptions:

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

[ExpectedException(typeof(Exception))]

Lequel de ceux-ci serait le meilleur? L'un offre-t-il des avantages par rapport à l'autre? Ou est-ce simplement une question de préférence personnelle?


3
Une troisième option est le style courant:Assert.That(() => MethodThatThrows(), Throws.Exception)
Jack Ukleja

1
NUnit version 3 et les versions ultérieures ne prennent plus en charge l' ExpectedExceptionattribut, donc pour la version 3+, seule la Assert.Throwsvariante est pertinente.
joanlofe

Pourquoi en est-il ainsi? Que Nunit3 a décidé de supprimer ce support? Je cherchais sur Google et je ne trouvais pas d'explication ... JUnit supporte toujours de cette façon, n'est-ce pas?
ahaaman

Réponses:


92

Le premier vous permet de tester plus d'une exception, avec plusieurs appels:

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

Le second ne vous permet de tester qu'une seule exception par fonction de test.


25
Un test ne devrait tester qu'un seul bit distinct de logique, donc le test de deux erreurs dans le même test unitaire ne serait-il pas considéré comme une mauvaise pratique?
SamuelDavis

5
@SamuelDavis - en général, vous ne voudriez pas tester différents cas dans le même test. Cependant, il peut y avoir un cas d'utilisation pour plusieurs Assert.Throws.
chue x

3
Dans tous les cas, vous obtenez ici l'exception en tant que paramètre, ce qui vous permet d'affirmer des détails dans l'exception. En outre, l'utilisation de "Exception attendue" ne vous protège pas pour le même type d'exception levé dans un autre appel de méthode. Ici, vous ciblez la méthode exacte et non l'ensemble du test. Même si votre test doit appeler très peu de code, vous n'êtes jamais trop en sécurité. Surtout quand le code devient complexe et / ou l'exception trop générique. Des trucs comme "ArgumentNullExceptions" peuvent être lancés beaucoup et seraient par exemple facilement manqués en utilisant ExpectedException. Assert.Throws ne le manquerait pas.
Gil Sand

254

La principale différence est:

ExpectedException()L'attribut rend le test réussi si une exception se produit à n'importe quel endroit de la méthode de test.
L'utilisation de Assert.Throws()permet de spécifier l' exactemplacement du code où une exception est attendue.

NUnit 3.0 supprime ExpectedExceptioncomplètement le support officiel .

Donc, je préfère définitivement utiliser la Assert.Throws()méthode plutôt que l' ExpectedException()attribut.


7
C'est de loin la bonne réponse. Incidemment, Assert.Throws () renvoie également l'exception, ce qui peut permettre une inspection supplémentaire des propriétés de l'exception, si elles sont importantes pour vous.
perfectionniste

1
Enfin, répondez pourquoi je ne peux pas faire fonctionner ExpectedException .. avec la version 3.
JanT

2
Voici le lien github.com/nunit/docs/wiki/Breaking-Changes - ExpectedExceptionAttribute n'est plus pris en charge.
Anton Lyhin

Pour que cela fonctionne sous NUnit 3.0, changez- le comme suit
Andrei Krasutski

38

Je préfère assert.throws car cela me permet de vérifier et d'affirmer d'autres conditions une fois l'exception levée.

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

    }

C'est l'une des meilleures réponses, il est assez courant que vous souhaitiez vérifier que quelque chose est entré dans un état d'erreur après le déclenchement de l'exception.
Rhys Bevilaqua

11

Vous pouvez également taper fortement l'erreur que vous attendez (comme l'ancienne version d'attrib).

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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.