web-dev-qa-db-fra.com

Comment puis-je Moq une méthode qui a un argument optionnel dans sa signature sans le spécifier explicitement ou en utilisant une surcharge?

Étant donné l'interface suivante:

public interface IFoo
{
    bool Foo(string a, bool b = false);
}

Essayer de s'en moquer avec Moq:

var mock = new Mock<IFoo>();
mock.Setup(mock => mock.Foo(It.IsAny<string>())).Returns(false);

donne l'erreur suivante lors de la compilation:

Une arborescence d'expression ne peut pas contenir un appel ou une invocation utilisant des arguments facultatifs

J'ai trouvé le problème ci-dessus soulevé sous la forme d'une amélioration dans la liste des problèmes de Moq et il semble être attribué à la version 4.5 (à chaque fois).

Ma question est la suivante: que dois-je faire étant donné que ce qui précède ne sera pas réglé de si tôt? Mes options ne permettent-elles que de définir explicitement la valeur par défaut du paramètre facultatif chaque fois que je le moque (ce qui annule le point de spécifier un en premier lieu), ou de créer une surcharge sans le booléen (comme ce que j’aurais fait?) avant C # 4)?

Ou quelqu'un a-t-il trouvé un moyen plus intelligent de surmonter ce problème?

100
Appulus

Je pense que votre seul choix pour le moment est d’inclure explicitement le paramètre bool dans la configuration de Foo.

Je ne pense pas que cela vole l'objectif de la spécification d'une valeur par défaut. La valeur par défaut est pratique pour appeler du code, mais je pense que vous devriez être explicite dans vos tests. Supposons que vous puissiez omettre de spécifier le paramètre bool. Que se passe-t-il si, à l'avenir, quelqu'un modifie la valeur par défaut de b en true? Cela conduira à l'échec des tests (et à juste titre), mais ils seront plus difficiles à corriger en raison de l'hypothèse cachée que b est false. Spécifier explicitement le paramètre bool présente un autre avantage: il améliore la lisibilité de vos tests. Quelqu'un en passant par eux saura rapidement qu'il existe une fonction Foo qui accepte deux paramètres. C'est mes 2 centimes, au moins :)

Pour ce qui est de le spécifier chaque fois que vous le simulez, ne dupliquez pas le code: créez et/ou initialisez le simulacre dans une fonction, de sorte que vous n’ayez qu’un seul point de changement. Si vous le souhaitez vraiment, vous pouvez surmonter l’inconvénient apparent de Moq en dupliquant les paramètres de Foo dans cette fonction d’initialisation:

public void InitFooFuncOnFooMock(Mock<IFoo> fooMock, string a, bool b = false)
{
    if(!b)
    {
        fooMock.Setup(mock => mock.Foo(a, b)).Returns(false);
    }
    else
    {
        ...
    }
}
75
Chris Mantle

À peine rencontré ce problème aujourd'hui, Moq ne prend pas en charge ce cas d'utilisation. Donc, il semble que le dépassement de la méthode serait suffisant pour ce cas.

public interface IFoo
{
    bool Foo(string a);

    bool Foo(string a, bool b);
}

Maintenant les deux méthodes sont disponibles et cet exemple fonctionnerait:

var mock = new Mock<IFoo>();
mock.Setup(mock => mock.Foo(It.IsAny<string>())).Returns(false);
7
Gil Grossman