Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing a method accepting a delegate with Moq

my code is using a component implementing an interface like this

public interface IFoo 
{ 
    void DoSomething(string p1);

    void DoSomething(string p1, Action<string> p2);
}

As of this moment, I'm using the first method, but I plan to move to the second one and I want to keep my coverage as high as possible.

Just that I really don't know how to inspect the delegate or even just setup Moq to mock the interface.

I tried with

mock.Setup(p => p.DoSomething(It.IsAny<string>(), It.IsAny<Delegate>()));
mock.Setup(p => p.DoSomething(It.IsAny<string>(), It.IsAny<Action<string>>()));

but neither will let me build. Any suggestion?

like image 611
Kralizek Avatar asked Sep 15 '15 20:09

Kralizek


1 Answers

The line:

mock.Setup(p => p.DoSomething(It.IsAny<string>(), It.IsAny<Delegate>()));

must not compile becaue DoSomething requires an Action<string>, and Delegate is not implicitly convertible to Action<string>. Your other line:

mock.Setup(p => p.DoSomething(It.IsAny<string>(), It.IsAny<Action<string>>()));

works and is correct!

You can setup only when p2 satisfies some criterion, for example:

mock.Setup(p => p.DoSomething(It.IsAny<string>(),
    It.Is((Action<string> p2) => p2 != null && p2.Target is SomeClass)
    ));

Or you can use CallBack to check things:

mock.Setup(p => p.DoSomething(It.IsAny<string>(), It.IsAny<Action<string>>()))
    .CallBack((string p1, Action<string> p2) =>
    {
        // your code (for example Asserts) here,
        // use p2
    });

Of course, there is a limit to how much you can inspect an Action<string>, but you can see if it is non-null, see if its p2.Target is non-null or has a specific type or equals a given instance, you can see if p2.Method is a known (named) method, or you could use p2.GetInvocationList() if you expect a so-called multicast delegate.

like image 80
Jeppe Stig Nielsen Avatar answered Sep 29 '22 19:09

Jeppe Stig Nielsen