2008-11-02 7 views
5

Je suis complètement nouveau chez C# et NUnit.Est-ce que ExpectedExceptionAttribute de NUnit seulement moyen de tester si quelque chose soulève une exception?

Dans Boost.Test il existe une famille de macros BOOST_*_THROW. Dans le module de test de Python, il y a la méthode TestCase.assertRaises. Pour autant que je sache, en C# avec NUnit (2.4.8), la seule méthode de test d'exception est d'utiliser ExpectedExceptionAttribute. Pourquoi devrais-je préférer ExpectedExceptionAttribute - disons - l'approche de Boost.Test? Quel raisonnement peut soutenir cette décision de conception? Pourquoi est-ce mieux dans le cas de C# et NUnit?

Enfin, si je décide d'utiliser ExpectedExceptionAttribute, comment puis-je faire des tests supplémentaires après que l'exception a été levée et interceptée? Disons que je veux tester l'exigence en disant que l'objet doit être valide après un setter System.IndexOutOfRangeException. Comment corrigeriez-vous le code suivant pour compiler et fonctionner comme prévu?

[Test] 
public void TestSetterException() 
{ 
    Sth.SomeClass obj = new SomeClass(); 

    // Following statement won't compile. 
    Assert.Raises("System.IndexOutOfRangeException", 
        obj.SetValueAt(-1, "foo")); 

    Assert.IsTrue(obj.IsValid()); 
} 

Edit: Merci pour vos réponses. Aujourd'hui, j'ai trouvé un C'est les testsblog entry où les trois méthodes décrites par vous sont mentionnées (et une autre variation mineure). Il est dommage que je ne pouvais pas trouver avant :-(

Répondre

13

Je suis surpris que je ne l'ai pas vu ce modèle encore mentionné. David Arno est de très similaire, mais je préfère la simplicité de cette:

try 
{ 
    obj.SetValueAt(-1, "foo"); 
    Assert.Fail("Expected exception"); 
} 
catch (IndexOutOfRangeException) 
{ 
    // Expected 
} 
Assert.IsTrue(obj.IsValid()); 
+0

Will not Assert.Fail ("...") vous expulser du test avec une exception AssertionFailedException? –

+1

Oui. Cependant, si l'appel à SetValueAt déclenche une exception (ce que nous voulons), le contrôle passe immédiatement au catch-block et contourne Assert.Fail, passant ainsi le test. Si SetValueAt ne lance pas d'exception, le comportement n'est pas exclu et le test doit échouer. – yfeldblum

+0

C'est plus propre que ma façon de le faire. Je vais utiliser votre approche à l'avenir :) –

10

Si vous pouvez utiliser NUnit 2.5 il y a une belle helpers il

Assert.That(delegate { ... }, Throws.Exception<ArgumentException>()) 
+1

+1. Je préfère utiliser ce style car il y a moins de cérémonie requise pour écrire le test, surtout si vous devez garder une référence pour vérifier les messages, etc. Vous pouvez également utiliser var exception = Assert.Throws (() => myInstance.DoSomethingInvalid ()); –

2

J'ai toujours adopté l'approche suivante:..

bool success = true; 
try { 
    obj.SetValueAt(-1, "foo"); 
} catch() { 
    success = false; 
} 

assert.IsFalse(success); 

... 
+0

Personnellement, j'attraperais une exception spécifique, mais cela fonctionnera ;-p –

+0

@Marc, point valide: il devrait attraper l'exception spécifique en cours de test et laisser les autres passer pour qu'ils apparaissent comme des erreurs plutôt que comme des échecs de test. –

4

La syntaxe MbUnit est

Assert.Throws<IndexOutOfRangeException>(delegate { 
    int[] nums = new int[] { 0, 1, 2 }; 
    nums[3] = 3; 
}); 
2

Votre syntaxe préférée:

Assert.Raises("System.IndexOutOfRangeException", 
       obj.SetValueAt(-1, "foo")); 

travail woiuldn't avec C# de toute façon - la obj.SetValueAt serait évaluée et le résultat passé à Assert.Raises. Si SetValue renvoie une exception, vous ne pourrez jamais entrer dans Assert.Raises.

Vous pouvez écrire une méthode d'aide pour le faire:

void Raises<T>(Action action) where T:Exception { 
    try { 
     action(); 
     throw new ExpectedException(typeof(T)); 
    catch (Exception ex) { 
     if (ex.GetType() != typeof(T)) { 
     throw; 
     } 
    } 
} 

Ce qui permet la syntaxe similaire:

Assert.Raises<System.IndexOutOfRangeException>(() => 
    obj.SetValueAt(-1, "foo") 
; 
Questions connexes