J'ai plusieurs modèles différents que j'utilise. J'utilise l' ExpectedException
attribut la plupart du temps lorsqu'une exception est attendue. Cela suffit dans la plupart des cas, cependant, dans certains cas, cela ne suffit pas. L'exception peut ne pas être capturable - puisqu'elle est lancée par une méthode qui est invoquée par réflexion - ou peut-être que je veux simplement vérifier que d'autres conditions sont respectées, disons qu'une transaction est annulée ou qu'une valeur a toujours été définie. Dans ces cas, je l'enveloppe dans un try/catch
bloc qui attend l'exception exacte, fait un Assert.Fail
si le code réussit et intercepte également les exceptions génériques pour m'assurer qu'une exception différente n'est pas levée.
Premier cas:
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void MethodTest()
{
var obj = new ClassRequiringNonNullParameter( null );
}
Deuxième cas:
[TestMethod]
public void MethodTest()
{
try
{
var obj = new ClassRequiringNonNullParameter( null );
Assert.Fail("An exception should have been thrown");
}
catch (ArgumentNullException ae)
{
Assert.AreEqual( "Parameter cannot be null or empty.", ae.Message );
}
catch (Exception e)
{
Assert.Fail(
string.Format( "Unexpected exception of type {0} caught: {1}",
e.GetType(), e.Message )
);
}
}
Assert.Throws
méthode fortement typée qui couvre ces deux cas.Maintenant, 2017, vous pouvez le faire plus facilement avec le nouveau Framework MSTest V2 :
la source
System.Exception
est lancé. Tout autre, comme unSystem.ArgumentException
échouera au test.Assert.ThrowsException<MyException>
testera uniquement par rapport au type d'exception fourni, et non à l'un de ses types d'exception dérivés. Dans mon exemple, si le testSub
était àThrow
unMyInheritedException
(type dérivé de la classe de baseMyException
), le test échouerait .Try { SubToTest(); Assert.Fail("...") } Catch (AssertFailedException e) {throw;} Catch (MyException e) {...}
. Notez la plus haute importance deCatch (AssertFailedException e) {throw;}
(cf. commentaire de allgeek)Je suis nouveau ici et je n'ai pas la réputation de commenter ou de voter contre, mais je voulais souligner une faille dans l'exemple de la réponse d'Andy White :
Dans tous les frameworks de tests unitaires que je connais,
Assert.Fail
fonctionne en lançant une exception, donc le catch générique masquera en fait l'échec du test. SiSomethingThatCausesAnException()
ne lance pas, laAssert.Fail
volonté, mais cela ne sera jamais envoyé au testeur pour indiquer un échec.Si vous avez besoin d'attraper l'exception attendue (c'est-à-dire pour affirmer certains détails, comme le message / les propriétés sur l'exception), il est important d'attraper le type attendu spécifique, et non la classe Exception de base. Cela permettrait à l'
Assert.Fail
exception de sortir (en supposant que vous ne lançiez pas le même type d'exception que votre cadre de test unitaire), mais permettrait toujours la validation de l'exception qui a été levée par votreSomethingThatCausesAnException()
méthode.la source
À partir de la version 2.5, NUnit a les niveaux de méthode suivants
Assert
pour tester les exceptions:Assert.Throws , qui testera un type d'exception exact:
Et
Assert.Catch
, qui testera une exception d'un type donné, ou un type d'exception dérivé de ce type:En passant, lors du débogage de tests unitaires qui lèvent des exceptions, vous souhaiterez peut-être empêcher VS de rompre sur l'exception .
Éditer
Juste pour donner un exemple du commentaire de Matthew ci-dessous, le retour du générique
Assert.Throws
etAssert.Catch
est l'exception avec le type de l'exception, que vous pouvez ensuite examiner pour une inspection plus approfondie:la source
Assert.Throws
, en plus il renvoie l'exception pour que vous puissiez écrire d'autres assertions sur l'exception elle-même.Malheureusement, MSTest TOUJOURS n'a vraiment que l'attribut ExpectedException (montre juste à quel point MS se soucie de MSTest) quel IMO est assez horrible car il rompt le modèle Arrange / Act / Assert et ne vous permet pas de spécifier exactement quelle ligne de code vous attendez à l'exception se produire.
Lorsque j'utilise (/ forcé par un client) pour utiliser MSTest, j'utilise toujours cette classe d'assistance:
Exemple d'utilisation:
la source
Au lieu d'utiliser l'
ExpectedException
attribut, je définis parfois deux méthodes utiles pour mes classes de test:AssertThrowsException()
prend un délégué et affirme qu'il lève l'exception attendue avec le message attendu.AssertDoesNotThrowException()
prend le même délégué et affirme qu'il ne lève pas d'exception.Ce jumelage peut être très utile lorsque vous souhaitez tester qu'une exception est levée dans un cas, mais pas dans l'autre.
En les utilisant, mon code de test unitaire pourrait ressembler à ceci:
Sympa et soigné hein?
Les méthodes My
AssertThrowsException()
etAssertDoesNotThrowException()
sont définies sur une classe de base commune comme suit:la source
Marquez le test avec ExpectedExceptionAttribute (c'est le terme dans NUnit ou MSTest; les utilisateurs d'autres frameworks de test unitaire peuvent avoir besoin de traduire).
la source
Avec la plupart des frameworks de test unitaire .net, vous pouvez mettre un attribut [ExpectedException] sur la méthode de test. Cependant, cela ne peut pas vous dire que l'exception s'est produite au moment où vous vous y attendiez. C'est là que xunit.net peut vous aider.
Avec xunit, vous avez Assert.Throws, vous pouvez donc faire des choses comme ceci:
[Fact] est l'équivalent xunit de [TestMethod]
la source
Suggérer d 'utiliser la syntaxe de délégué propre de NUnit .
Exemple de test
ArgumentNullExeption
:la source