Using Moq to Mock a Func<> constructor parameter and Verify it was called twice

22,713

Solution 1

I don't think it is necessary to use a mock for the Func.

You can simply create an ordinary Func yourself that returns a mock of IFooBarProxy:

int numberOfCalls = 0;
Func<IFooBarProxy> func = () => { ++numberOfCalls;
                                  return new Mock<IFooBarProxy>(); };

var sut = new FooBar(func);

sut.Process();

Assert.Equal(2, numberOfCalls);

Solution 2

As of at least Moq 4.5.28, you can mock and verify the Func as you would expect to be able to. I couldn't tell when this feature was added (according to the original question at some point this did not work).

[Test]
public void TestFoobar()
{
    var funcMock = new Mock<Func<IFooBarProxy>>();
    var fooBar = new FooBar(funcMock.Object);
    fooBar.Process();
    funcMock.Verify(x => x(), Times.AtLeast(2));
}

Solution 3

Since Moq v4.1.1308.2120

As of this version, which was released some months after this question was asked (Aug 21, 2013), the functionality to mock a Func<> has been added. So with any current version of mock, you can use var funcMock = new Mock<Func<IFooBarProxy>>();.

Original (outdated) answer

If you have a lot of callback Func's, Actions, etc, it's better to define a helper interface in your tests and mock that interface. This way you can use the regular Moq functionality, like setting up return values, testing input arguments, etc.

interface IFooBarTestMethods
{
    IFooBarProxy FooBarProxyFactory();
}

Usage

var testMethodsMock = new Mock<IFooBarTestMethods>();
testMethodsMock
    .Setup(x => x.FooBarProxyFactory())
    .Returns(new Mock<IFooBarProxy>());

var sut = new FooBar(testMethodsMock.Object.FooBarProxyFactory);
testMethodsMock.Verify(x => x.FooBarProxyFactory(), Times.Exactly(2));
Share:
22,713
thehumansaredead
Author by

thehumansaredead

Updated on February 10, 2020

Comments

  • thehumansaredead
    thehumansaredead about 4 years

    Taken the question from this article (How to moq a Func) and adapted it as the answer is not correct.

    public class FooBar
    {
        private Func<IFooBarProxy> __fooBarProxyFactory;
    
        public FooBar(Func<IFooBarProxy> fooBarProxyFactory)
        {
            _fooBarProxyFactory = fooBarProxyFactory;
        }
    
        public void Process() 
        {
            _fooBarProxyFactory();
            _fooBarProxyFactory();
        }
    }
    

    I have a need to mock a Func<> that is passed as a constructor parameter, the assert that the func was call twice.

    When trying to mock the function var funcMock = new Mock<Func<IFooBarProxy>>(); Moq raises and exception as the Func type is not mockable.

    The issue is that without mocking the func it is not possible to verify that the func was called (n) times. funcMock.Verify( (), Times.AtLeast(2));

  • HelloWorld
    HelloWorld almost 4 years
    that does compile ??? should it not be new Mock<IFooBarProxy>().Object ;-)
  • Daniel Hilgarth
    Daniel Hilgarth almost 4 years
    @HelloWorld This code is over 7 years old. Maybe Mock was changed since then? If you are sure how to correct it - please test it in real code - feel free to edit. As you can see from the other answers, Mock was indeed changed afterwards