web-dev-qa-db-fra.com

MOQ - vérifier que l'exception a été levée

Je travaille avec le framework MOQ pour mes tests. J'ai un scénario dans lequel je m'attends à ce qu'une exception de faute soit levée. Comment puis-je vérifier qu'il a été lancé?

public void Koko(List<string?> list) 
{ 
   foreach(string? str in list) 
   { 
        if (str != null) someProperty.Foo(str); 
        else throw new FormatException(); 
   } 
} 

Merci d'avance.

23
Gal Ziv

Si vous voulez vérifier qu'une exception a été levée (par votre propre code), Moq n'est pas votre outil de choix pour cela. Utilisez simplement l'un des frameworks de tests unitaires disponibles.

Xunit/NUnit:

Assert.Throws<SomeException>(() => foo.Bar());

Assertions fluides:

Action act = () => foo.Bar();
act.ShouldThrow<SomeException>();

http://fluentassertions.codeplex.com/documentation

http://www.nunit.org/index.php?p=exceptionAsserts&r=2.6.2

27
treze

Je me trompe peut-être sur votre intention, mais pour autant que je sache, il n'est pas nécessaire de faire quoi que ce soit à une maquette pour vérifier que l'exception a été levée.

Il semble que vous ayez une classe avec une méthode Foo qui prend une chaîne - appelons cette InnerClass

public class InnerClass {
    public virtual void Foo(string str) {
         // do something with the string
    }
}

et une classe qui contient un InnerClass comme propriété (someProperty) qui a un membre Koko qui prend une List <string> comme paramètre

public class OuterClass {

    private readonly InnerClass someProperty;

    public OuterClass(InnerClass someProperty) {
        this.someProperty = someProperty;
    }

    public void Koko(List<string> list) {
         foreach (var str in list) {
              if (str != null)
                   someProperty.Foo(str);
              else
                   throw new FormatException();
          }
    } 
}

REMARQUE: Je ne peux pas obtenir List <chaîne?> À compiler - me dit que le type sous-jacent (chaîne) ne doit pas être nullable. AFAIK, il suffit de rendre les types de valeur nullables, les types de référence sont implicitement nullables.

Il semble que vous souhaitiez tester que si vous passez une liste de chaînes où l'une d'entre elles est nulle, une exception FormatException est levée.

Si c'est le cas, alors la seule raison d'un MOQ est de nous libérer de s'inquiéter de la fonctionnalité InnerClass. Foo est une méthode, donc, à moins que nous n'utilisions des simulations strictes, nous pouvons simplement créer une maquette InnerClass sans aucune autre configuration.

Il existe un attribut [ExpectedException] avec lequel nous pouvons étiqueter notre test pour vérifier que l'exception a été levée.

[TestMethod]
[ExpectedException(typeof(FormatException))]
public void ExceptionThrown() {

    var list = new List<string>() {
        "Abel",
        "Baker",
        null,
        "Charlie"
    };

    var outer = new OuterClass(new Mock<InnerClass>().Object);
    outer.Koko(list);

}

Ce test réussira si une exception FormatException est levée et échouera dans le cas contraire.

24
AlanT

Veuillez lire ceci Introduction à Moq . Voici la façon de configurer InvalidOperationException à lancer lorsque la méthode DoSomething est invoquée:

mock.Setup(foo => foo.DoSomething()).Throws<InvalidOperationException>();

Vérifiez ensuite simplement si la méthode a été appelée. Si elle a été appelée, une exception a été levée

mock.Verify(foo => foo.DoSomething());
11
Sergey Berezovskiy

Vous pouvez tester qu'une exception est levée à l'aide de NUnit Asserts:

Assert.That(() => testObject.methodToTest(), Throws.TypeOf<FaultException>());
10
g t

Une vieille question mais pas de code source montrant réellement quelle était la solution, alors voici ce que j'ai fait:

var correctExceptionThrown = false;

try
{
    _myClass.DoSomething(x);
}
catch (Exception ex)
{
    if (ex.Message == "Expected message")
        correctExceptionThrown = true;
}                    

Assert.IsTrue(correctExceptionThrown);

Notez plutôt que de vérifier le message, vous pouvez intercepter un type particulier d'exception (généralement préférable).

7
Ronnie

En lisant ces réponses, j'ai réalisé qu'il y avait encore une autre façon de le faire en utilisant NUnit. Ce qui suit obtient le texte d'exception à partir d'une exception et vérifie le texte du message d'erreur.

var ex = Assert.Throws<SomeException>(() => foo.Bar());
Assert.That(ex.Message, Is.EqualTo("Expected exception text");

Et je n'ai pas pu faire fonctionner la syntaxe de décoration/attribut (réponse d'AlanT ci-dessus) en utilisant la dernière version de NUnit - je ne sais pas pourquoi, mais cela s'est plaint quoi que j'aie essayé de faire.

6
DaveN59

Ok donc je l'ai résolu de la manière suivante.

Puisque l'exception a cassé mon test, j'ai mis l'appel de méthode dans le bloc Parce que dans try-catch.

Ensuite, je pourrais utiliser une simple vérification.

Merci à tous les assistants ...

2
Gal Ziv