-->

Verifying a delegate was called with Moq

2020-06-06 20:42发布

问题:

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.

回答1:

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


回答2:

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


回答3:

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.



回答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())


回答5:

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.