Fehler CS0854, wenn Sie Moq mit optionalen Parametern verwenden

Fehler CS0854, wenn Sie Moq mit optionalen Parametern verwenden

Problem

Optionale Parameter sind nicht optional, wenn Sie Moq verwenden.

Wenn Sie einen Methodenaufruf für ein Scheinobjekt einrichten oder überprüfen und die Methode einen optionalen Parameter hat, für den Sie keinen Wert angegeben haben, erhalten Sie den folgenden Compilerfehler:

Dieser seltsame Fehler ist nicht spezifisch für Moq. Es passiert jedes Mal, wenn Sie versuchen, optionale Parameter mit einem Ausdrucksbaum zu verwenden (System.Linq.Ausdrücke). Moq verwendet Ausdrucksbaumparameter, weshalb Sie bei der Verwendung von Moq häufig auf diesen Fehler stoßen. Hier ist zum Beispiel die Methode Moq Setup():

public ISetup<T> Setup(Expression<Action<T>> expression);
Code language: C# (cs)

Um diesen Fehler zu beheben, müssen Sie Werte für alle optionalen Parameter in der Methode übergeben, die Sie verspotten. Ich zeige unten ein Beispiel.

Hinweis:Die von der IDE vorgeschlagenen Korrekturen für diesen Fehler sind nicht sinnvoll und erhöhen nur die Verwirrung darüber.

Lösung:Sie müssen einen Wert für den optionalen Parameter angeben

Angenommen, Sie möchten die folgende Repository-Schnittstelle nachahmen:

public interface IRepository
{
	public void Save(bool inTransaction=false);
}
Code language: C# (cs)

Die Methode Save() hat einen optionalen Parameter. Wenn Sie versuchen, die Save()-Methode für das Scheinobjekt einzurichten/zu überprüfen, erhalten Sie den CS0854-Fehler:

var mockRepo = new Mock<IRepository>();
var service = new Service(mockRepo.Object);

mockRepo.Setup(t => t.Save()).Throws(new Exception());

service.Save();

mockRepo.Verify(t => t.Save());
Code language: C# (cs)

Um dies zu beheben, müssen Sie einen Wert für den optionalen Parameter in den Aufrufen von Save() übergeben, etwa so:

var mockRepo = new Mock<IRepository>();
var service = new Service(mockRepo.Object);

mockRepo.Setup(t => t.Save(true)).Throws(new Exception());

service.Save();

mockRepo.Verify(t => t.Save(It.IsAny<bool>()));
Code language: C# (cs)

Beachten Sie, dass Sie einen fest codierten Wert (wie Save(true)) übergeben können ), oder Sie können It.IsAny() übergeben wenn der für den Parameter verwendete spezifische Wert für Ihren Test keine Rolle spielt.