How do I Moq a method that has an optional argument in its signature without explicitly specifying it or using an overload?
Solution 1:
I believe your only choice right now is to explicitly include the bool
parameter in the setup for Foo
.
I don't think it defeats the purpose of specifying a default value. The default value is a convenience for calling code, but I think that you should be explicit in your tests. Say you could leave out specifying the bool
parameter. What happens if, in future, someone changes the default value of b
to true
? This will lead to failing tests (and rightfully so), but they will be more difficult to fix because of the hidden assumption that b
is false
. Explicitly specifying the bool
parameter has another benefit: it improves the readability of your tests. Someone going through them will quickly know that there's one Foo
function that accepts two parameters. That's my 2 cents, at least :)
As for specifying it every time you mock it, don't duplicate code: create and/or initialise the mock in a function, so that you only have a single point of change. If you really want to, you can overcome Moq's apparent short-coming here by duplicating Foo
's parameters into this initialisation function:
public void InitFooFuncOnFooMock(Mock<IFoo> fooMock, string a, bool b = false)
{
if(!b)
{
fooMock.Setup(mock => mock.Foo(a, b)).Returns(false);
}
else
{
...
}
}
Solution 2:
Just encountered this issue today, Moq doesn't support this use case. So, seems that overriding the method would be sufficient for this case.
public interface IFoo
{
bool Foo(string a);
bool Foo(string a, bool b);
}
Now both methods are available and this example would work:
var mock = new Mock<IFoo>();
mock.Setup(mock => mock.Foo(It.IsAny<string>())).Returns(false);
Solution 3:
Using Moq version 4.10.1 I have been able to do the following
With Interface:
public interface IFoo
{
bool Foo(string a, bool b = false);
}
And Mock
var mock = new Mock<IFoo>();
mock.Setup(mock => mock.Foo(It.IsAny<string>(), It.IsAny<bool>())).Returns(false);
Resolves a call to Foo with the first parameter okay