Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invoking Func passed as a parameter to a mock using Moq and C#

I have a mocked method that looks like this:


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

In my code, I do such as:


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

My case is, I am testing MyMethod with Moq and I want to verify the Func behaviour is as expected. I have some injected objects in its body, that are mocks, and should be verified; it also starts building my return value, so I can't do any assertion unless I invoke the function passed as parameter.

In Java and jUnit + EasyMock , I would capture the parameter passed, like this:


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

How do I do the same using C# + Moq?

like image 604
Luís Guilherme Avatar asked Apr 18 '12 18:04

Luís Guilherme


People also ask

What is MOQ mock?

Moq is a mocking framework built to facilitate the testing of components with dependencies. As shown earlier, dealing with dependencies could be cumbersome because it requires the creation of test doubles like fakes. Moq makes the creation of fakes redundant by using dynamically generated types.

What is CallBase in MOQ?

CallBase , when initialized during a mock construction, is used to specify whether the base class virtual implementation will be invoked for mocked dependencies if no setup is matched. The default value is false . This is useful when mocking HTML/web controls of the System.

What is verifiable in MOQ?

Verifiable is to enlist a Setup into a set of "deferred Verify(...) calls" which can then be triggered via mock. Verify() .


1 Answers

You can capture invocation argument when provide Returns for method:

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

Here is complete test for your 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));            
}

Also you need test for case when mockInjected1.Method returns false.

like image 157
Sergey Berezovskiy Avatar answered Oct 24 '22 06:10

Sergey Berezovskiy