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);
    }
}
Était-ce utile?

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 ...)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top