86 votes

SetupSequence dans Moq

Je veux un simulateur qui renvoie 0 la première fois, puis renvoie 1 à chaque fois que la méthode est appelée par la suite. Le problème est que si la méthode est appelée 4 fois, je dois écrire :

mock.SetupSequence(x => x.GetNumber())
    .Returns(0)
    .Returns(1)
    .Returns(1)
    .Returns(1);

Sinon, la méthode renvoie null.

Existe-t-il un moyen d'écrire que, après l'appel initial, la méthode renvoie 1 ?

70voto

Jakub Konecki Points 28852

La méthode la plus propre consiste à créer un Queue et passer .Dequeue pour Returns

.Returns(new Queue<int>(new[] { 0, 1, 1, 1 }).Dequeue);

56voto

Romain Verdier Points 8699

Ce n'est pas particulièrement fantaisiste, mais je pense que ça pourrait marcher :

    var firstTime = true;

    mock.Setup(x => x.GetNumber())
        .Returns(()=>
                        {
                            if(!firstTime)
                                return 1;

                            firstTime = false;
                            return 0;
                        });

17voto

Connor Low Points 1606

J'arrive un peu tard, mais si vous voulez continuer à utiliser l'API de Moq, vous pouvez appeler la fonction Setup dans l'action sur la finale Returns appeler :

var mock = new Mock<IFoo>();
mock.SetupSequence(m => m.GetNumber())
    .Returns(4)
    .Returns(() =>
    {
        // Subsequent Setup or SetupSequence calls "overwrite" their predecessors: 
        // you'll get 1 from here on out.
        mock.Setup(m => m.GetNumber()).Returns(1);
        return 1;
    });

var o = mock.Object;
Assert.Equal(4, o.GetNumber());
Assert.Equal(1, o.GetNumber());
Assert.Equal(1, o.GetNumber());
// etc...

Je voulais faire une démonstration en utilisant StepSequence mais pour le cas spécifique du PO, vous pourriez simplifier et tout mettre dans un fichier de type Setup méthode :

mock.Setup(m => m.GetNumber())
    .Returns(() =>
    {
        mock.Setup(m => m.GetNumber()).Returns(1);
        return 4;
    });

J'ai tout testé ici avec xunit@2.4.1 y Moq@4.14.1 - passe ✔

5voto

sloth Points 40517

Vous pouvez utiliser une variable temporaire pour garder la trace du nombre de fois où la méthode a été appelée.

Exemple :

public interface ITest
{ Int32 GetNumber(); }

static class Program
{
    static void Main()
    {
        var a = new Mock<ITest>();

        var f = 0;
        a.Setup(x => x.GetNumber()).Returns(() => f++ == 0 ? 0 : 1);

        Debug.Assert(a.Object.GetNumber() == 0);
        for (var i = 0; i<100; i++)
            Debug.Assert(a.Object.GetNumber() == 1);
    }
}

5voto

Thomas Heijtink Points 165

Il suffit de mettre en place une méthode d'extension comme :

public static T Denqueue<T>(this Queue<T> queue)
{
    var item = queue.Dequeue();
    queue.Enqueue(item);
    return item;
}

Et ensuite configurer le retour comme :

var queue = new Queue<int>(new []{0, 1, 1, 1});
mock.Setup(m => m.GetNumber).Returns(queue.Denqueue);

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