Question Comment est-ce que j'utilise Assert pour vérifier qu'une exception a été levée?


Comment est-ce que j'utilise Assert (ou autre classe de test?) Pour vérifier qu'une exception a été levée?


671
2018-06-01 05:01


origine


Réponses:


Pour "Visual Studio Team Test", il apparaît que vous appliquez l'attribut ExpectedException à la méthode du test.

Échantillon de la documentation ici: Une procédure pas à pas de test d'unité avec le test d'équipe Visual Studio

[TestMethod]
[ExpectedException(typeof(ArgumentException),
    "A userId of null was inappropriately allowed.")]
public void NullUserIdInConstructor()
{
   LogonInfo logonInfo = new LogonInfo(null, "P@ss0word");
}

804
2018-06-01 05:09



Habituellement, votre cadre de test aura une réponse à cela. Mais si ce n'est pas assez flexible, vous pouvez toujours le faire:

try {
    somethingThatShouldThrowAnException();
    Assert.Fail(); // If it gets to this line, no exception was thrown
} catch (GoodException) { }

Comme @Jonas le souligne, cela ne fonctionne PAS pour attraper une exception de base:

try {
    somethingThatShouldThrowAnException();
    Assert.Fail(); // raises AssertionException
} catch (Exception) {
    // Catches the assertion exception, and the test passes
}

Si vous devez absolument attraper Exception, vous devez renvoyer le fichier Assert.Fail (). Mais vraiment, c'est un signe que vous ne devriez pas écrire ceci à la main; Vérifiez votre cadre de test pour les options, ou voyez si vous pouvez lancer une exception plus significative à tester.

catch (AssertionException) { throw; }

Vous devriez être capable d'adapter cette approche à ce que vous voulez - y compris en spécifiant les types d'exceptions à attraper. Si vous ne vous attendez qu'à certains types, terminez catch bloque avec:

} catch (GoodException) {
} catch (Exception) {
    // not the right kind of exception
    Assert.Fail();
}

222
2018-06-01 05:06



Ma méthode préférée pour implémenter ceci est d'écrire une méthode appelée Throws, et l'utiliser comme n'importe quelle autre méthode Assert. Malheureusement, .NET ne vous permet pas d'écrire une méthode d'extension statique, donc vous ne pouvez pas utiliser cette méthode comme si elle appartenait à la classe Assert; Il suffit de faire un autre appelé MyAssert ou quelque chose de similaire. La classe ressemble à ceci:

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace YourProject.Tests
{
    public static class MyAssert
    {
        public static void Throws<T>( Action func ) where T : Exception
        {
            var exceptionThrown = false;
            try
            {
                func.Invoke();
            }
            catch ( T )
            {
                exceptionThrown = true;
            }

            if ( !exceptionThrown )
            {
                throw new AssertFailedException(
                    String.Format("An exception of type {0} was expected, but not thrown", typeof(T))
                    );
            }
        }
    }
}

Cela signifie que votre test unitaire ressemble à ceci:

[TestMethod()]
public void ExceptionTest()
{
    String testStr = null;
    MyAssert.Throws<NullReferenceException>(() => testStr.ToUpper());
}

Qui ressemble et se comporte beaucoup plus comme le reste de vos syntaxes de test unitaires.


98
2018-04-12 11:20



Si vous utilisez MSTest, qui n'avait initialement pas de ExpectedException attribut, vous pouvez le faire:

try 
{
    SomeExceptionThrowingMethod()
    Assert.Fail("no exception thrown");
}
catch (Exception ex)
{
    Assert.IsTrue(ex is SpecificExceptionType);
}

56
2018-06-01 05:10



Méfiez-vous de l'utilisation de ExpectedException, car cela peut conduire à plusieurs pièges comme démontré ici:

http://geekswithblogs.net/sdorman/archive/2009/01/17/unit-testing-and-expected-exceptions.aspx

Et ici:

http://xunit.github.io/docs/comparisons.html

Si vous devez tester des exceptions, il y a moins d'inconvénients. Vous pouvez utiliser la méthode try {act / fail} catch {assert}, qui peut être utile pour les frameworks qui ne supportent pas directement les tests d'exception autres que ExpectedException.

Une meilleure alternative est d'utiliser xUnit.NET, qui est un framework de test unitaire très moderne, orienté vers l'avenir et extensible qui a appris de toutes les autres erreurs, et qui a été amélioré. Une telle amélioration est Assert.Throws, qui fournit une syntaxe bien meilleure pour l'affirmation des exceptions.

Vous pouvez trouver xUnit.NET sur github: http://xunit.github.io/


36
2018-06-01 05:22



Si vous utilisez NUNIT, vous pouvez faire quelque chose comme ceci:

Assert.Throws<ExpectedException>(() => methodToTest());


Il est également possible de stocker l'exception levée afin de la valider davantage:

ExpectedException ex = Assert.Throws<ExpectedException>(() => methodToTest());
Assert.AreEqual( "Expected message text.", ex.Message );
Assert.AreEqual( 5, ex.SomeNumber);

Voir: http://nunit.org/docs/2.5/exceptionAsserts.html


34
2017-12-04 11:02



Dans un projet sur lequel je travaille, nous avons une autre solution.

D'abord, je n'aime pas l'attribut ExpectedExceptionAttribute parce qu'il prend en considération l'appel de méthode qui a provoqué l'exception.

Je fais cela avec un helpermethod à la place.

Tester

[TestMethod]
public void AccountRepository_ThrowsExceptionIfFileisCorrupt()
{
     var file = File.Create("Accounts.bin");
     file.WriteByte(1);
     file.Close();

     IAccountRepository repo = new FileAccountRepository();
     TestHelpers.AssertThrows<SerializationException>(()=>repo.GetAll());            
}

HelperMethod

public static TException AssertThrows<TException>(Action action) where TException : Exception
    {
        try
        {
            action();
        }
        catch (TException ex)
        {
            return ex;
        }
        Assert.Fail("Expected exception was not thrown");

        return null;
    }

Neat, n'est-ce pas;)


24
2017-10-01 21:13



C'est un attribut de la méthode de test ... vous n'utilisez pas Assert. Ressemble à ça:

[ExpectedException(typeof(ExceptionType))]
public void YourMethod_should_throw_exception()

15
2018-06-01 05:09