it-swarm.com.de

Wie kann ich eine Methode mit einem optionalen Argument in der Signatur festlegen, ohne es explizit anzugeben oder eine Überladung zu verwenden?

Angesichts der folgenden Schnittstelle:

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

Versuch, es mit Moq zu verspotten:

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

gibt beim Kompilieren den folgenden Fehler aus:

Ein Ausdrucksbaum darf keinen Aufruf oder Aufruf enthalten, der optionale Argumente verwendet

Ich habe das oben genannte Problem als Verbesserung in der Liste der Probleme von Moq gefunden und es scheint der Version 4.5 zugewiesen zu sein (wann immer dies der Fall ist).

Meine Frage ist: Was soll ich tun, wenn die oben genannten Probleme nicht in Kürze behoben werden? Sind meine Optionen nur, um entweder den Standardwert des optionalen Parameters jedes Mal, wenn ich ihn verspotte, explizit festzulegen (was den Punkt, an dem ich einen spezifiziere, zunichte macht) oder um eine Überladung ohne den Bool zu erzeugen (wie ich es getan hätte)? vor C # 4)?

Oder hat jemand einen geschickteren Weg gefunden, um dieses Problem zu lösen?

100
Appulus

Ich glaube, Sie haben im Moment nur die Wahl, den Parameter bool explizit in das Setup für Foo aufzunehmen.

Ich denke nicht, dass es den Zweck der Angabe eines Standardwerts zunichte macht. Der Standardwert ist eine Annehmlichkeit für das Aufrufen von Code, aber ich denke, dass Sie in Ihren Tests explizit sein sollten. Angenommen, Sie könnten den Parameter bool weglassen. Was passiert, wenn in Zukunft jemand den Standardwert von b in true ändert? Dies wird zu Testfehlern führen (und das zu Recht), aber es wird schwieriger sein, sie zu beheben, weil die versteckte Annahme, dass bfalse ist. Die explizite Angabe des Parameters bool hat einen weiteren Vorteil: Sie verbessert die Lesbarkeit Ihrer Tests. Jemand, der sie durchläuft, wird schnell wissen, dass es eine Foo -Funktion gibt, die zwei Parameter akzeptiert. Das sind zumindest meine 2 Cent :)

Duplizieren Sie den Code nicht, wenn Sie ihn bei jeder Verspottung angeben: Erstellen und/oder initialisieren Sie den Verspottungscode in einer Funktion, sodass Sie nur einen einzigen Änderungspunkt haben. Wenn Sie wirklich wollen, können Sie das offensichtliche Manko von Moq überwinden, indem Sie die Parameter von Foo in diese Initialisierungsfunktion kopieren:

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

Dieses Problem ist erst heute aufgetreten. Moq unterstützt diesen Anwendungsfall nicht. Es scheint also, dass das Überschreiben der Methode für diesen Fall ausreichend wäre.

public interface IFoo
{
    bool Foo(string a);

    bool Foo(string a, bool b);
}

Jetzt sind beide Methoden verfügbar und dieses Beispiel würde funktionieren:

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