I had difficulty replicating this. I think there's a typo in your verify:
MockEntities.Verify(x => x.AttachAsModifiedToOrders(It.IsAny<Order>(), It.IsAny<Expression<Func<IOrder, object>>>()), Times.Exactly(1));
Should be:
MockEntities.Verify(x => x.AttachAsModifiedToOrders(It.IsAny<Order>(), It.IsAny<Expression<Func<IOrder, object[]>>>()), Times.Exactly(1));
I also wonder if the first It.IsAny should be the interface and not the concrete type?
However, this is a overly-complicated test of some bit of functionality, and the code sample is missing a few pieces, like the DataAccess type or class instance (not sure?), Order, and Orders.
To work around that, I created the IOrder interface and a manipulator object that uses the interface, its a bit nonsensical, but it drives the test:
public interface IOrder
{
void AttachAsModifiedToOrders(IOrder order, params Expression<Func<IOrder, object[]>>[] modifiedProperties);
}
public class Manipulator
{
public Manipulator(IOrder order)
{
Expression<Func<IOrder, object[]>> exp = o => new object[0];
order.AttachAsModifiedToOrders(order, exp);
}
public void DoStuff() { }
}
I then created a test fixture to validate the params arg:
[TestFixture]
public class Tester
{
[Test]
public void Test()
{
var order = new Mock<IOrder>();
order.Setup(n => n.AttachAsModifiedToOrders(It.IsAny<IOrder>()));
var manipulator = new Manipulator(order.Object);
manipulator.DoStuff();
order.Verify(x => x.AttachAsModifiedToOrders(It.IsAny<IOrder>(), It.IsAny<Expression<Func<IOrder, object[]>>>()), Times.Once());
}
}
This works for me, so I don't think the problem is the params value and Moq directly. I do think you'd be well off to take a step back and see if you are really unit testing the class that interacts with the Mock, or trying to verify integrated usages of a couple different types. The params and expression tree is a bit of a smell also.
Best Answer
I believe your only choice right now is to explicitly include the
bool
parameter in the setup forFoo
.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 ofb
totrue
? This will lead to failing tests (and rightfully so), but they will be more difficult to fix because of the hidden assumption thatb
isfalse
. Explicitly specifying thebool
parameter has another benefit: it improves the readability of your tests. Someone going through them will quickly know that there's oneFoo
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: