[英]Moq an indexed property and use the index value in the return/callback
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. 我想要moq一个具有索引的属性,并且我希望能够在回调中使用索引值,就像在moq方法的回调中使用方法参数一样。 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>
. 编辑:为了澄清,我希望
get
的回调/返回方法是Func<int,int>
,并且set
的回调/返回方法是Action<int,int>
。 Trying what Mike suggested, you can sort of do this for set
, but with one major limitation: 尝试迈克建议,你可以为
set
做这个,但有一个主要的限制:
mock.SetupSet(m => m[23] = It.IsAny<int>())
.Callback(DoSet).Verifiable();
The callback DoSet
is indeed then called with values (23,<any>)
. 然后使用值
(23,<any>)
调用回调DoSet
。 Unfortunately, using It.IsAny<int>()
instead of 23
seems to behave as 0
, rather than <any>
. 不幸的是,使用
It.IsAny<int>()
而不是23
似乎表现为0
,而不是<any>
。
Also, I couldn't find a way of calling SetupGet
with Returns
where Returns
takes a Func<int,int>
that would even compile. 另外,我找不到使用
Returns
调用SetupGet
的方法,其中Returns
采用甚至可以编译的Func<int,int>
。
Is it possible to use Moq for this? 是否可以使用Moq?
Motivation: I'm just playing with Moq, attempting to use it to provide a fluent API for performing interception. 动机:我只是在玩Moq,试图用它来提供一个流畅的API来执行拦截。 That is, given an interface
I
and an instance X
of I
, automatically create a Mock<I>
proxy with behaviour defaulting to X
. 即,给定的接口
I
和实例X
的I
,自动创建一个Mock<I>
与行为默认为代理X
。
Would probably make more sense to work directly with Castle DP, but I like the Moq Expression Tree syntax. 直接使用Castle DP可能更有意义,但我喜欢Moq Expression Tree语法。
As of Moq 4.2.1502.0911 for .NET Framework 4.5, I found the following behavior to be true. 从.NET Framework 4.5的Moq 4.2.1502.0911开始,我发现以下行为是正确的。
The problem you're running into is specifically due to the It.IsAny<T>
call. 您遇到的问题特别是由于
It.IsAny<T>
调用。 If you use It.IsAny<T>
, the callback does not execute: 如果使用
It.IsAny<T>
,则回调不会执行:
[Test]
public void DoesNotExecuteCallback()
{
// Arrange
var mock = new Mock<IIndexable>();
var called = false;
mock.SetupSet(m => m[It.IsAny<int>()] = It.IsAny<int>()).Callback<int,int>((x, y) => called = true);
var instance = mock.Object;
// Act
instance[1] = 2;
// Arrange
Assert.That(called, Is.False);
}
But if you call it using specific parameters, it calls the callback: 但是如果你使用特定参数调用它,它会调用回调:
[Test]
public void DoesExecuteCallback()
{
// Arrange
var mock = new Mock<IIndexable>();
var called = false;
mock.SetupSet(m => m[1] = 2).Callback<int,int>((x, y) => called = true);
var instance = mock.Object;
// Act
instance[1] = 2;
// Arrange
Assert.That(called, Is.True);
}
To summarize, you should avoid the use of the It.IsAny
when trying to setup expectations for an indexer. 总而言之,在尝试设置索引器的期望时,应避免使用
It.IsAny
。 In general, you should be avoiding the use of it because it can encourage sloppy test writing 一般来说,你应该避免使用它,因为它可以鼓励草率的测试写作
There are appropriate use cases for It.IsAny
, but without knowing the specifics I tend to recommend against it. 有适当的用例
It.IsAny
,但不知道我倾向于建议反对的具体细节。
The method SetupSet
takes a plain delegate, not an expression tree of type Expression<...>
like many other Moq methods. 方法
SetupSet
采用普通委托,而不像许多其他Moq方法那样使用Expression<...>
类型的表达式树。
For that reason Moq cannot see that you used It.IsAny
. 出于这个原因,Moq看不到您使用过
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
. 相反,
It.IsAny
被调用 (不是我们想要的),而Moq只看到它的返回值恰好是default(int)
或0
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.