42
votes

i got a class that gets by argument a delegate. This class invokes that delegate, and i want to unit test it with Moq. how do i verify that this method was called ?

example class :

public delegate void Foo(int number);

public class A
{
   int a = 5;

   public A(Foo myFoo)
   {
      myFoo(a);
   }
}

and I want to check that Foo was called. Thank you.

5
I think that you need to change the answer accepted, because the @Lukazoid 's answer is more right than your choice.Claudio Santos
In the constructor, should the line read myFoo(a)? You are invoking that instance of Foo, not the Foo class itself, right?Wisco crew

5 Answers

64
votes

As of this commit Moq now supports the mocking of delegates, for your situation you would do it like so:

var fooMock = new Mock<Foo>();
var a = new A(fooMock.Object);

Then you can verify the delegate was invoked:

fooMock.Verify(f => f(5), Times.Once);

Or:

fooMock.Verify(f => f(It.IsAny<int>()), Times.Once);
37
votes

What about using an anonymous function? It can act like an inline mock here, you don't need a mocking framework.

bool isDelegateCalled = false;
var a = new A(a => { isDelegateCalled = true});

//do something
Assert.True(isDelegateCalled);
4
votes

You can do something like that:

 public interface IWithFOOMethod
 {
     void FooAlikeMethod(int number);
 }

 Mock<IWithFOOMethod> myMock = new Mock<IWithFOOMethod>();

 A a = new A(myMock.Object.FooAlikeMethod);

 myMock.Verify(call => call.Foo(It.IsAny<int>()), Times.Once())
4
votes

Moq does not support mocking delegates. But you can create some interface, with method, which matches your delegate signature:

public interface IBar
{
    void M(int number);
}

Then create mock, which implements this interface, and use this mock object to create delegate:

Mock<IBar> bar = new Mock<IBar>();
Foo foo = new Foo(bar.Object.M); 
A a = new A(foo);
bar.Verify(x => x.M(5));   

After exercising your sut, you will be able to verify expectations on your mocked object.

UPDATE: Actually you can simply pass bar.Object.M to your sut, without Foo delegate instance creation. But anyway, mocking delegates requires interface creation.

1
votes

Since Moq doesn't support mocking delegates, I'll usually handle this with something like:

var list = new List<int> ();
var del = i => list.Add (i);
var a = new A(del);
list.ShouldContainOnly (new[] { 5 });

where the delegate provided performs some simple, verifiable action.