46

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.

Technetium
  • 5,902
  • 2
  • 43
  • 54
Lironess
  • 823
  • 1
  • 11
  • 19
  • 5
    I think that you need to change the answer accepted, because the @Lukazoid 's answer is more right than your choice. – Claudio Santos Sep 18 '14 at 11:08
  • In the constructor, should the line read `myFoo(a)`? You are invoking that instance of `Foo`, not the `Foo` class itself, right? – Wisco crew Oct 20 '17 at 21:52

5 Answers5

73

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);
Lukazoid
  • 19,016
  • 3
  • 62
  • 85
37

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);
Ufuk Hacıoğulları
  • 37,978
  • 12
  • 114
  • 156
  • 1
    Nice, but... The question **specifically** asks about Moq. – rsenna Aug 01 '18 at 14:54
  • 2
    @rsenna If you read the answer below, you will see that it wasn't supported in Moq when I posted my answer. I provided a solution for the verification OP was trying to do. – Ufuk Hacıoğulları Aug 01 '18 at 14:59
  • 1
    The OP probably also found that adequate, which is, again, nice. But it doesn't change the fact that it does not solve **my** problem - which could be described by the very same title in this question here. :-) – rsenna Aug 01 '18 at 15:14
  • 1
    Somehow this thread made me laugh :D I hope you guys are having fun writing code as well :D – Hao Zhang Jun 30 '20 at 19:19
4

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.

Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
  • Just an FYI, Moq now supports the mocking of delegates see my answer and [here](https://github.com/Moq/moq4/commit/e614ae5b4a14896503b59e2a70ac799bb66e741b) – Lukazoid Sep 11 '14 at 19:00
4

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())
eyossi
  • 4,230
  • 22
  • 20
1

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.

Pete
  • 11,313
  • 4
  • 43
  • 54
  • 2
    Just an FYI, Moq now supports the mocking of delegates see my answer and [here](https://github.com/Moq/moq4/commit/e614ae5b4a14896503b59e2a70ac799bb66e741b) – Lukazoid Sep 11 '14 at 18:59