2012-04-18 11 views
8

tengo un método burlado que tiene este aspecto:Invocación Func pasa como parámetro a una maqueta usando Moq y C#


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

En mi código, lo hago como:


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; 
} 

Mi caso es que estoy probando MyMethod con Moq y quiero verificar que el comportamiento de Func sea el esperado. Tengo algunos objetos inyectados en su cuerpo, que son simulacros, y deben ser verificados; también comienza a construir mi valor de retorno, por lo que no puedo hacer ninguna aserción a menos que invoque la función pasada como parámetro.

En Java y jUnit + EasyMock, me gustaría capturar el parámetro pasado, como este:


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); 
} 

¿Cómo puedo hacer lo mismo usando C# + Moq?

Respuesta

9

Puede capturar argumento de invocación al proporcionar Returns para el método:

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

Aquí está la prueba completa de su código:

[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));    
} 

También es necesario prueba para el caso cuando mockInjected1.Method devuelve falso.

+0

ve muy bien, pero cuando lo hago, me sale el siguiente error: * Test' falló: System.NullReferenceException: Referencia a objeto no establecida como instancia de un objeto. en Prueba. b__0 (Func'1 capturado) * –

+1

@ LuísGuilherme ver muestra de prueba completa –

+0

Se trabajó desde el comienzo. Obtenía una referencia nula dentro de la llamada de Func :) –

Cuestiones relacionadas