NUnit, Ni Assert.Throws ni [ExpectedException] Catch Jeté Exception
Question
Avant de commencer, je tiens à préciser que je l'ai déjà vérifié des solutions dans les deux cette question et cette question.
La méthode pour tester
public static DataSet ExecuteDataSet(this SqlConnection connection, string sql)
{
if (null == connection || null == sql)
{
throw new ArgumentNullException();
}
using (var command = connection.CreateCommand())
{
// Code elided for brevity
}
}
Les méthodes d'essai
[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void ExecuteDataSetThrowsForNullConnection()
{
((SqlConnection)null).ExecuteDataSet("SELECT TOP 1 * FROM prep");
}
[Test]
public void ExecuteDataSetThrowsForNullSql()
{
Assert.Throws<ArgumentNullException>(
() => Resource.Connection.ExecuteDataSet(null)
);
}
Le comportement Odd
Ni version du test méthode est attrapant le ArgumentNullException
qui est jeté immédiatement en entrant dans la méthode ExecuteDataSet
. produit le contrôle de flux à la ligne suivante (de using (var command = connection.CreateCommand())
) et un NullReferenceException
se produit au lieu (qui, bien sûr, ne sont pas pris en charge par l'un de mes cas de test parce que il ne devrait jamais être jeté ).
A l'origine, la première méthode de test (ExecuteDataSetThrowsForNullConnection
) avait l'air comme le second (ExecuteDataSetThrowsForNullSql
). Lorsque Assert.Throws
n'a pas réussi à attraper l'exception, je l'ai fait des recherches et a noté que certaines personnes ont recommandé d'utiliser à la place ExpectedException
. J'ai modifié le code de test en conséquence, mais sans résultat.
Pour mémoire, ce code est .NET 3.5 32 bits, testé sous NUnit 2.5.9. J'utilise TestDriven.NET pour l'intégration de Visual Studio, et avoir les dernières versions de NCover et NDepend installé.
TL; DR Question
Pourquoi ne sont pas les méthodes d'essai attrapant les exception est levée, et comment puis-je résoudre ce problème?
EDIT
Cette version de la méthode d'essai fonctionne.
[Test]
public void ExecuteDataSetThrowsForNullConnection()
{
try
{
((SqlConnection)null).ExecuteDataSet("SELECT TOP 1 * FROM prep");
}
catch(ArgumentNullException e)
{
Assert.AreEqual(true, true);
}
catch (Exception e)
{
Assert.Fail("Expected ArgumentNullException, but {1} was thrown instead.", e.GetType().Name);
}
}
La solution
Je suppose que vous n'êtes pas vraiment tester le code que vous pensez que vous êtes. Essayez de mettre des déclarations Console.WriteLine
et voir si elles sont imprimées. Si vous mettez un point d'arrêt sur l'instruction throw
et exécutez les tests dans le débogueur, fait le point d'arrêt Touchés? Si le contrôle passe à l'instruction suivante, cela signifie que l'exception ne sont jamais jetés - il ne peut peut-être pris d'une manière qui laisserait l'exécution continue dans la méthode de lancer, à moins que vous avez trouvé un vraiment bizarre bug CLR.
J'ai écrit beaucoup de code comme ceci et il n'a jamais échoué dans NUnit.
En aparté, je considère comme une bonne pratique d'inclure le nom du paramètre dans ArgumentExceptions, donc je l'aurais écrit:
if (connection == null)
{
throw new ArgumentNullException("connection");
}
if (sql == null)
{
throw new ArgumentNullException("sql");
}
a le problème malheureux d'être éternise et en répétant les noms de paramètres dans le code sous forme de chaînes ... mais il est relativement facile d'obtenir le droit (en particulier avec ReSharper aider à valider les noms) et il pourrait être vraiment utile si ce jamais déclencheurs dans la production. (Il y a quelques hacks grotty pour valider les arguments d'une autre manière, mais je suppose que vous ne voulez pas voir les ...)