I have an interface with a few methods. I have a default implementation of this interface. For the purpose of integration tests I would like to create a mock implementation that returns my custom value if one of these methods is called, and falls back to the default implementation otherwise. Is it possible with Moq, or should I create a simple stub myself?
EXAMPLE
IInterface default = new DefaultImplementation();
var mock = new Mock<IInterface>();
mock.Setup(i => i.Method(It.IsAny<>())).Calls(p => p==0 ? return 5 : default.Method(p););
TheMethodITest(mock.Object()); //if it calls the object with 0 then it should get 5, otherwise it should call the default object
Moq, how it works The idea is to create a concrete implementation of an interface and control how certain methods on that interface responds when called. This will allow us to essentially test all of the paths through code.
The three key steps to using mock objects for testing are: Use an interface to describe the object. Implement the interface for production code. Implement the interface in a mock object for testing.
You can set the mock object property to the value returned by the mock object method. To achieve this, specify separate behaviors for the method and the property. You can specify one behavior at a time. For more information about mock object behavior, see Specify Mock Object Behavior.
Callbacks. A powerful capability of Moq is to attach custom code to configured methods and properties' getters and setters. This capability is often referred to as Callbacks.
You can do this, by setting the Mock to the concrete class and using As()
to retrieve the underlying IInterface
, on which the setup is done. You can then hard cast mock.Object
to invoke the underlying concrete object:
[Test]
public void SomeTest()
{
var mock = new Mock<DefaultImplementation>().As<IInterface>();
mock.Setup(i => i.Method(It.IsAny<int>()))
.Returns<int>(p => p == 0
? 5
: ((DefaultImplementation)mock.Object).Method(p));
TheMethodITest(mock.Object);
}
Here's the rest of the setup I tested with, FWIW:
public interface IInterface
{
int Method(int p);
}
public class DefaultImplementation : IInterface
{
public int Method(int p)
{
return 6;
}
}
[TestFixture]
public class SomeFixture
{
public static void TheMethodITest(IInterface dep)
{
for (var i = 0; i < 10; i++)
{
Debug.WriteLine("{0}:{1}",i, dep.Method(i));
}
}
}
I'm not sure what is the condition for providing default or your specific value. However, it sounds like you want to set up a mock instance with Delegator
.
public void MoqCanBeSetupWithDelegator()
{
var mock = new Mock<IInterface>();
Func<string, int> valueFunction = i => i == "true" ? 1 : default(int);
mock.Setup(x => x.Method(It.IsAny<string>())).Returns(valueFunction);
Assert.Equal(1, mock.Object.Method("true"));
Assert.Equal(0, mock.Object.Method("anonymous"));
}
public interface IInterface
{
int Method(string arg);
}
As you can see, the Returns
method is overloaded to accept a returned value(int
) or delegator representing the mocked method signature. You can use Func<string, int>
to replace the actual implementation - int Method(string arg)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With