I want to moq a property that has an index, and I want to be able to use the index values in the callback, the same way you can use method arguments in the callback for moq'd methods. Probably easiest to demonstrate with an example:
public interface IToMoq
{
int Add(int x, int y);
int this[int x] { get; set; }
}
Action<int, int> DoSet = (int x, int y) =>
{
Console.WriteLine("setting this[{0}] = {1}", x, y);
throw new Exception("Do I ever get called?");
};
var mock = new Mock<IToMoq>(MockBehavior.Strict);
//This works perfectly
mock.Setup(m => m.Add(It.IsAny<int>(), It.IsAny<int>()))
.Returns<int, int>((a, b) => a + b);
//This compiles, but my callback never seems to be called
mock.SetupSet(m => m[It.IsAny<int>()] = It.IsAny<int>())
.Callback(DoSet);
var obj = mock.Object;
Console.WriteLine("Add(3,4) => {0}", obj.Add(3, 4)); //Works perfectly
obj[1] = 2; //Does not throw, why?
Edit: To clarify, I want the callback/returns method for the get
to be Func<int,int>
, and the callback/returns method for the set
to be Action<int,int>
. Trying what Mike suggested, you can sort of do this for set
, but with one major limitation:
mock.SetupSet(m => m[23] = It.IsAny<int>())
.Callback(DoSet).Verifiable();
The callback DoSet
is indeed then called with values (23,<any>)
. Unfortunately, using It.IsAny<int>()
instead of 23
seems to behave as 0
, rather than <any>
.
Also, I couldn't find a way of calling SetupGet
with Returns
where Returns
takes a Func<int,int>
that would even compile.
Is it possible to use Moq for this?
Motivation: I'm just playing with Moq, attempting to use it to provide a fluent API for performing interception. That is, given an interface I
and an instance X
of I
, automatically create a Mock<I>
proxy with behaviour defaulting to X
.
Would probably make more sense to work directly with Castle DP, but I like the Moq Expression Tree syntax.
The method SetupSet
takes a plain delegate, not an expression tree of type Expression<...>
like many other Moq methods.
For that reason Moq cannot see that you used It.IsAny
. Instead, It.IsAny
is called (not what we want) and Moq sees its return value only which happens to be default(int)
, or 0
.