2012-04-18 10 views
8

Ho un metodo preso in giro che assomiglia a questo:Invocare Func passato come parametro per un mock utilizzando Moq e C#


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

Nel mio codice, lo faccio come ad esempio:


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

mio caso è, sto testando MyMethod con Moq e voglio verificare il comportamento di Func è come previsto. Ho alcuni oggetti iniettati nel suo corpo, che sono mock e dovrebbero essere verificati; inizia anche a costruire il mio valore di ritorno, quindi non posso fare alcuna asserzione a meno che non invoco la funzione passata come parametro.

in Java e JUnit + EasyMock, vorrei cogliere il parametro passato, in questo modo:


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

Come posso fare lo stesso utilizzando C# + Moq?

risposta

9

È possibile catturare argomento invocazione quando fornire Returns per il metodo:

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

Ecco test completo per il codice:

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

hai bisogno anche di test per caso quando mockInjected1.Method restituisce false.

+0

Sembra ottimo, ma quando lo faccio, viene visualizzato il seguente errore: * Test 'non riuscito: System.NullReferenceException: riferimento oggetto non impostato su un'istanza di un oggetto. al test. b__0 (Func'1 catturato) * –

+1

@ LuísGuilherme vedere il campione completo di prova –

+0

Ha funzionato dall'inizio. Stavo ricevendo un riferimento Null all'interno della chiamata Func :) –

Problemi correlati