webentwicklung-frage-antwort-db.com.de

Verwenden von moq, um nur einige Methoden zu verspotten

Ich habe folgende Methode:

public CustomObect MyMethod()
{
    var lUser = GetCurrentUser();
    if (lUser.HaveAccess)
    {
        //One behavior
    }
    else 
    {
        //Other behavior
    }

    //return CustomObject
}

Ich möchte IMyInterface.GetCurrentUser Verspotten, damit ich beim Aufrufen von MyMethod zu einem der Codepfade gelangen kann, um ihn zu überprüfen. Wie geht das mit Moq?

Ich mache folgendes:

var moq = new Mock<IMyInterface>();            
moq.Setup(x => x.GetCurrentUser()).Returns(lUnauthorizedUser);

//act
var lResult = moq.Object.MyMethod();

Aber aus irgendeinem Grund ist lResult immer null, und wenn ich versuche, im Debug auf MyMethod zuzugreifen, überspringe ich immer die nächste Anweisung.

58

Dies wird als partieller Mock bezeichnet, und für die Vorgehensweise in moq ist es erforderlich, die Klasse und nicht die Schnittstelle zu verspotten und anschließend die Eigenschaft "Callbase" für Ihr verspottetes Objekt auf "true" zu setzen.

Dazu müssen alle Methoden und Eigenschaften der zu testenden Klasse virtuell gemacht werden. Vorausgesetzt, dies ist kein Problem, können Sie einen Test wie den folgenden schreiben:

 var mock = new Mock<YourTestClass>();
 mock.CallBase = true;
 mock.Setup(x => x.GetCurrentUser()).Returns(lUnauthorizedUser);
 mockedTest.Object.MyMethod();
119
lee

Erweitern auf Lee Antwort ,

Sie müssen nicht alle Methoden und Eigenschaften Ihrer Klasse virtuell machen, sondern nur die, die Sie verspotten möchten.

Es sollte auch beachtet werden, dass Sie die konkrete Implementierung Ihrer Klasse verspotten sollten.

var mock = new Mock<YourTestClass>(); // vs. var mock = new Mock<IYourTestInterface>();

Wenn Ihre Klasse keinen Standardkonstruktor hat, müssen Sie auch Argumente angeben, die an sie übergeben werden sollen:

var mock = new Mock<YourTestClass>(x, y, z);
// or
var mock = new Mock<YourTestClass>(MockBehavior.Default, x, y, z);

Wo x, y, z sind der erste, zweite und dritte Parameter für Ihren Konstruktor.

Und wenn die Methode, die Sie verspotten möchten, geschützt ist, müssen Sie Moq.Protected

using Moq.Protected;

TReturnType returnValue = default(TReturnType);

mock.Protected()
    .Setup<TReturnType>("YourMockMethodName", It.IsAny<int>()) // methodname followed by arguments
    .Returns(returnValue);
22
Charles W

Ich hatte einen ähnlichen Fall. Mit dem folgenden Code konnte ich flexibler sowohl verspottete als auch tatsächliche Methoden aus einer bestimmten Implementierung einer Schnittstelle verwenden:

var mock = new Mock<ITestClass>(); // Create Mock of interface

// Create instance of ITestClass implementation you want to use
var inst = new ActualTestClass();

// Setup to call method of an actual instance
// if method returns void use mock.Setup(...).Callback(...)
mock.Setup(m => m.SomeMethod(It.IsAny<int>())
    .Returns((int x) => inst.SomeMethod(x));

Jetzt können Sie die eigentliche Methode verwenden, aber auch Dinge wie Verify verwenden, um zu sehen, wie oft sie aufgerufen wurde.

16
Brandon Rader