2012-04-18 3 views
8

Ich habe eine verspottet Methode, die wie folgt aussieht:Hervorrufen Func übergeben als Parameter an einem Mock mit Moq und C#


class NotMineClass { 
    T Execute(Func operation) 
    { 
    // do something 
    return operation(); 
    } 
} 

In meinem Code, ich weiß, wie:


public MyType MyMethod() 
{ 
    MyType object = new MyType(); 
    bool success = notMineClassInstance.Execute(() => 
    { 
    // some things 
    retVal = injectedObject1.method(); 
    object.attribute = injectedObject2.method(); 
    // some other things 
    return retVal; 
    } 
    if (success) 
    { 
    object.otherAttribute = someValue; 
    } 
    return object; 
} 

Meine Fall ist, ich teste MyMethod mit Moq und ich möchte überprüfen, ob das Func-Verhalten wie erwartet ist. Ich habe einige Objekte in seinen Körper injiziert, die Mocks sind, und sollten verifiziert werden; Es beginnt auch, meinen Rückgabewert zu erstellen, sodass ich keine Assertion ausführen kann, wenn ich nicht die als Parameter übergebene Funktion aufruft.

In Java und jUnit + EasyMock, würde ich die Parameter übergeben erfassen, wie folgt aus:


public void testMyMethod() { 
    // ... 
    Capture < Function < void, Boolean > > functionCapture = Captures.last(); 
    expect(notMineClassInstance.execute(EasyMock.capture(functionCapture))); 
    // Expectations for the body of the function 

    replay(); 

    functionCapture.getValue().apply(null); 
} 

Wie mache ich das gleiche mit C# + Moq?

Antwort

9

Sie können Aufruf Argument erfassen, wenn Returns für Verfahren zur Verfügung stellen:

Mock<NotMineClassInstance> mock = new Mock<NotMineClassInstance>(); 
mock.Setup(x => x.Execute<bool>(It.IsAny<Func<bool>>())) 
    .Returns((Func<bool> captured) => { captured(); return true; }); 

Hier vollständigen Test für Ihren Code:

[Test] 
public void TestingSomething() 
{ 
    // Arrange 
    Mock<NotMineClassInstance> mockNotMine = new Mock<NotMineClassInstance>(); 
    mockDep.Setup(x => x.Execute<bool>(It.IsAny<Func<bool>>())).Returns((Func<bool> func) => func()); 

    Mock<Injected1> mockInjected1 = new Mock<Injected1>(); 
    mockInjected1.Setup(i => i.Method()).Returns(true); 

    Mock<Injected2> mockInjected2 = new Mock<Injected2>(); 
    mockInjected2.Setup(i => i.Method()).Returns("xxx"); 

    YourClass yourObject = new YourClass(mockDep.Object, mockInjected1.Object, mockInjected2.Object); 

    // Act 
    MyType my = yourObject.MyMethod();  

    // Assert 
    mockNotMine.Verify(d => d.Execute<bool>(It.IsAny<Func<bool>>())); 
    mockInjected1.Verify(i => i.Method()); 
    mockInjected2.Verify(i => i.Method()); 

    Assert.That(my.Attribute, Is.EqualTo("xxx")); 
    Assert.That(my.OtherAttribute, Is.EqualTo(someValue));    
} 

Darüber hinaus müssen Sie Test für Fall, wenn mockInjected1.Method false zurückgibt.

+0

Sieht gut aus, aber wenn ich dies tue, erhalte ich den folgenden Fehler: * Test 'fehlgeschlagen: System.NullReferenceException: Objektreferenz nicht auf eine Instanz eines Objekts festgelegt. bei Test. b__0 (Func'1 erfasst) * –

+1

@ LuísGuilherme siehe vollständiges Testbeispiel –

+0

Es funktionierte seit dem Anfang. Ich bekam eine Null-Referenz innerhalb des Func-Anrufs :) –