Problem
I already have an interface set up…
public interface ISomeInterface
{
void SomeMethod();
}
I’ve also used a mixin to expand this interface…
public static class SomeInterfaceExtensions
{
public static void AnotherMethod(this ISomeInterface someInterface)
{
// Implementation here
}
}
I have a class that calls this, and I’d like to test it…
public class Caller
{
private readonly ISomeInterface someInterface;
public Caller(ISomeInterface someInterface)
{
this.someInterface = someInterface;
}
public void Main()
{
someInterface.AnotherMethod();
}
}
I’d like to mock the interface and verify the call to the extension method, as well as a test where I’d like to mock the interface and verify the call to the extension method…
[Test]
public void Main_BasicCall_CallsAnotherMethod()
{
// Arrange
var someInterfaceMock = new Mock<ISomeInterface>();
someInterfaceMock.Setup(x => x.AnotherMethod()).Verifiable();
var caller = new Caller(someInterfaceMock.Object);
// Act
caller.Main();
// Assert
someInterfaceMock.Verify();
}
However, running this test results in an exception…
System.ArgumentException: Invalid setup on a non-member method:
x => x.AnotherMethod()
I’m wondering whether there’s a good method to mimic out the mixin call.
Asked by Russell Giddings
Solution #1
To get around this issue, I’ve utilized a Wrapper. Make a wrapper object with your mocked method and pass it to it.
Paul Irwin’s Mocking Static Methods for Unit Testing contains several good examples.
Answered by Alvis
Solution #2
With the mocking framework, you can’t “directly” imitate a static method (thus the extension method). Moles (http://research.microsoft.com/en-us/projects/pex/downloads.aspx) is a free Microsoft utility that takes a different approach. The following is the tool’s description:
Moles can be used with any testing framework (it is platform agnostic).
Answered by Daniele Armanasco
Solution #3
I discovered that I needed to look into the extension method for which I was trying to mimic the input and mock what was going on there.
Using an extension seemed to me to be the same as explicitly adding code to your method. This meant that instead of mocking the extension itself, I had to ridicule what occurred inside it.
Answered by chris31389
Solution #4
When I’m wrapping an object, I like to use the wrapper (adapter pattern). I’m not sure I’d wrap an extension method that isn’t part of the object with that.
I inject (swap out) the method using an internal Lazy Injectable Property of type Action, Func, Predicate, or Delegate.
internal Func<IMyObject, string, object> DoWorkMethod
{
[ExcludeFromCodeCoverage]
get { return _DoWorkMethod ?? (_DoWorkMethod = (obj, val) => { return obj.DoWork(val); }); }
set { _DoWorkMethod = value; }
} private Func<IMyObject, string, object> _DoWorkMethod;
Then, instead of calling the method, you call the Func.
public object SomeFunction()
{
var val = "doesn't matter for this example";
return DoWorkMethod.Invoke(MyObjectProperty, val);
}
Check out http://www.rhyous.com/2016/08/11/unit-testing-calls-to-complex-extension-methods/ for a more detailed example.
Answered by Rhyous
Solution #5
You can check the Invocations property on the mimicked object if you just want to make sure the extension method was called without trying to set a return value.
Like this:
var invocationsCount = mockedObject.Invocations.Count;
invocationsCount.Should().BeGreaterThan(0);
Answered by Clinton Avery
Post is based on https://stackoverflow.com/questions/2295960/mocking-extension-methods-with-moq