63 votes

Définition des valeurs de variable dans un appel Callback() de Moq

Je pense que je pourrais être un peu confus sur la syntaxe des méthodes de rappel Moq. Lorsque j'essaie de faire quelque chose comme ceci :

IFilter filter = new Filter();
List objects = new List { new Foo(), new Foo() };  

IQueryable myFilteredFoos = null;
mockObject.Setup(m => m.GetByFilter(It.IsAny()))
   .Callback( (IFilter filter) => myFilteredFoos = filter.FilterCollection(objects))
   .Returns(myFilteredFoos.Cast());

Cela lance une exception car myFilteredFoos est null pendant l'appel à Cast(). Est-ce que cela ne fonctionne pas comme je m'y attends ? Je penserais que FilterCollection serait appelé et ensuite myFilteredFoos serait non-null et permettrait la conversion.

FilterCollection n'est pas capable de retourner un null, ce qui me conduit à la conclusion qu'il n'est pas appelé. De plus, lorsque je déclare myFilteredFoos comme ceci :

Queryable myFilteredFoos;

L'appel Return se plaint que myFilteredFoos peut être utilisé avant son initialisation.

90voto

Mark Seemann Points 102767

Cela est dû au fait que le code dans la méthode Returns est évalué immédiatement ; c'est-à-dire, lorsque la méthode Setup est invoquée.

Cependant, le rappel n'est pas invoqué avant que la méthode GetByFilter soit appelée.

Heureusement, la méthode Returns est surchargée de sorte que vous puissiez aussi différer son exécution :

mockObject.Setup(m => m.GetByFilter(It.IsAny()))
    .Callback((IFilter filter) =>
        myFilteredFoos = filter.FilterCollection(objects))
    .Returns(() => myFilteredFoos.Cast());

Cependant, vous n'avez pas besoin de sauvegarder la valeur dans un rappel, car vous pouvez juste obtenir la valeur du paramètre directement dans la méthode Returns :

mockObject.Setup(m => m.GetByFilter(It.IsAny()))
    .Returns((IFilter filter) =>
        filter.FilterCollection(objects).Cast());

24voto

Vous pouvez simplement prendre le paramètre dans la valeur de retour...

mockObject
  .Setup(m => m.GetByFilter(It.IsAny()))
  .Returns((IFilter filter) =>
    {
      myFilteredFoos = filter.FilterCollection(objects);

      return myFilteredFoos.Cast();
    });

0voto

sathish Points 99

Cela est dû à la manière dont nous utilisons la méthode Return

si nous utilisons Return(GetObject2(object1)) l'objet1 ne sera jamais initialisé à partir du rappel, donc il échouera à se convertir en Object2

La bonne manière de faire est comme ceci Return(()=> GetObject2()), nous devons faire en sorte que la méthode Return spécifie une fonction qui calculera la valeur à retourner de la méthode

N'oubliez pas d'utiliser la clé de fonction ()=>

Exemple ci-dessous, pour votre référence

var object1= new List();
mockObj.Setup(_ =>_.GetMethod(It.IsAny>()))
            .Callback>((obj1) =>
            {
                object1= obj1;
            })
            .Returns(()=> GetObject2(object1));

 private List GetObject2(List object1){
     return object1.select(_=> new Object2())
 }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X