web-dev-qa-db-fra.com

C #: Comment vérifier «aucune exception n'est survenue» dans mon test unitaire MSTest?

J'écris un test unitaire pour cette méthode qui retourne "void". Je voudrais avoir un cas où le test réussit quand aucune exception n'est levée. Comment écrire cela en C #?

Assert.IsTrue(????)

(Je suppose que c'est comme ça que je devrais vérifier, mais ce qui entre dans "???")

J'espère que ma question est suffisamment claire.

70
CuriousGeorge

Votre test unitaire échouera de toute façon si une exception est levée - vous n'avez pas besoin de mettre une assertion spéciale.

C'est l'un des rares scénarios où vous verrez des tests unitaires sans assertions du tout - le test échouera implicitement si une exception est levée.

Cependant, si vous vouliez vraiment écrire une assertion pour cela - peut-être pour pouvoir attraper l'exception et signaler "aucune exception attendue mais j'ai obtenu ceci ...", vous pouvez le faire:

[Test]
public void TestNoExceptionIsThrownByMethodUnderTest()
{
    var myObject = new MyObject();

    try
    {
        myObject.MethodUnderTest();
    }
    catch (Exception ex)
    {
        Assert.Fail("Expected no exception, but got: " + ex.Message);
    }
}

(ce qui précède est un exemple pour NUnit, mais il en va de même pour MSTest)

117
Rob Levine

Dans NUnit, vous pouvez utiliser:

Assert.DoesNotThrow(<expression>); 

pour affirmer que votre code ne lève pas d'exception. Bien que le test échoue si une exception est levée même s'il n'y a pas d'assertion autour de lui, la valeur de cette approche est que vous pouvez alors faire la distinction entre les attentes non satisfaites et les bogues dans vos tests, et vous avez la possibilité d'ajouter un message personnalisé qui sera affiché dans votre sortie de test. Une sortie de test bien formulée peut vous aider à localiser les erreurs dans votre code qui ont provoqué l'échec d'un test.

Je pense qu'il est valable d'ajouter des tests pour s'assurer que votre code ne lève pas d'exceptions; par exemple, imaginez que vous validez une entrée et que vous devez convertir une chaîne entrante en une longue. Il peut arriver que la chaîne soit nulle, ce qui est acceptable, vous devez donc vous assurer que la conversion de chaîne ne lève pas d'exception. Il y aura donc du code pour gérer cette occasion, et si vous n'avez pas écrit de test pour cela, il vous manquera une couverture autour d'un élément logique important.

23
Clarkeye

Ne testez pas quelque chose ça n'arrive pas . C'est comme s'assurer que le code ne casse pas. C'est en quelque sorte implicite, nous nous efforçons tous d'obtenir un code sans interruption et sans bogue. Vous voulez faire des tests pour ça? Pourquoi une seule méthode? Ne voulez-vous pas que toutes vos méthodes soient testées pour qu'elles ne lèvent pas d'exception? En suivant cette route, vous vous retrouverez avec un test supplémentaire, factice, sans assertions pour chaque méthode de votre base de code. Cela n'apporte aucune valeur.

Bien sûr, si votre exigence est de vérifier que la méthode détecte des exceptions, vous testez cela (ou en l'inversant un bit; testez qu'il ne lance pas ce qu'il est censé attraper).

Cependant, l'approche/les pratiques générales restent intactes - vous n'écrivez pas de tests pour certaines exigences artificielles/vagues qui sont hors de portée du code testé (et tester que "ça marche" ou "ne jette pas" est généralement un exemple de tels - en particulier dans les scénarios où les responsabilités de la méthode sont bien connues).

Pour faire simple, concentrez-vous sur ce que votre code doit faire et testez-le.

11
k.m

Cette classe d'aide m'a gratté les dents avec MSTest. Peut-être que ça peut aussi rayer le vôtre.

[TestMethod]
public void ScheduleItsIneligibilityJob_HasValid_CronSchedule()
{
    // Arrange
    var factory = new StdSchedulerFactory();
    IScheduler scheduler = factory.GetScheduler();

    // Assert
    AssertEx.NoExceptionThrown<FormatException>(() =>
        // Act
        _service.ScheduleJob(scheduler)
    );
}

public sealed class AssertEx
{
    public static void NoExceptionThrown<T>(Action a) where T:Exception
    {
        try
        {
            a();
        }
        catch (T)
        {
            Assert.Fail("Expected no {0} to be thrown", typeof(T).Name);
        }
    }
}
5
JJS

J'aime voir un Assert.Whatever À la fin de chaque test, juste pour la cohérence ... sans un, puis-je vraiment être sûr qu'il n'y en a pas censé y être?

Pour moi, c'est aussi simple que de mettre Assert.IsTrue(true);

Je sais je n'ai pas accidentellement mis ce code là-dedans, et donc je devrais être assez confiant au survol rapide que c'était comme prévu.

    [TestMethod]
    public void ProjectRejectsGappedVersioningByDefault() {

        var files = new List<ScriptFile>();
        files.Add(ScriptProjectTestMocks.GetVersion1to2());
        files.Add(ScriptProjectTestMocks.GetVersion3to4());

        Assert.Throws<ScriptProject.InvalidProjectFormatException>(() => {
            var sut = new ScriptProject(files);
        });

    }

    [TestMethod]
    public void ProjectAcceptsGappedVersionsExplicitly() {

        var files = new List<ScriptFile>();
        files.Add(ScriptProjectTestMocks.GetVersion1to2());
        files.Add(ScriptProjectTestMocks.GetVersion3to4());

        var sut = new ScriptProject(files, true);

        Assert.IsTrue(true);   // Assert.Pass() would be nicer... build it in if you like

    }
2
jleach