【发布时间】:2015-04-17 11:02:57
【问题描述】:
我想最小化一个具有索引的属性,并且我希望能够在回调中使用索引值,就像您可以在回调中使用方法参数来获取最小量的方法一样。可能最容易用一个例子来演示:
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?
编辑:澄清一下,我希望get 的回调/返回方法为Func<int,int>,set 的回调/返回方法为Action<int,int>。尝试 Mike 的建议,您可以为 set 执行此操作,但有一个主要限制:
mock.SetupSet(m => m[23] = It.IsAny<int>())
.Callback(DoSet).Verifiable();
回调DoSet 确实是用值(23,<any>) 调用的。不幸的是,使用It.IsAny<int>() 而不是23 似乎表现得像0,而不是<any>。
另外,我找不到用Returns 调用SetupGet 的方法,其中Returns 需要一个甚至可以编译的Func<int,int>。
是否可以为此使用最小起订量?
动机:我只是在玩 Moq,试图用它来提供一个流畅的 API 来执行拦截。也就是说,给定一个接口I 和一个I 的实例X,自动创建一个Mock<I> 代理,其行为默认为X。
直接使用 Castle DP 可能更有意义,但我喜欢 Moq 表达式树语法。
【问题讨论】:
-
对我来说似乎是一个错误。使用
mock.SetupSet(c => c[1] = It.IsAny<int>()).Callback(DoSet);设置模拟按预期工作,mock.SetupSet(c => c[It.IsAny<int>()] = It.IsAny<int>()).Callback(DoSet);使用MockBehavior.Strict失败,并且对MockBehavior.Loose不执行任何操作。 -
使用
mock.SetupSet(x => x[It.IsAny<int>()] = It.IsAny<int>()).Callback(doSet);和obj[0] = 1; obj[1] = 2;,它对零索引按预期工作。它在索引 1 上失败(或其他任何事情)。 -
@Rob:你运行的是什么版本的起订量?我实际上遇到了两种不同的行为。我正在检查我在两个独立项目中运行的 Moq 版本,一个似乎可以工作,另一个没有。
-
@Mike - 我也在使用两个版本,不过为了让它正常工作,我暂时升级到 4.2.1502
-
@Rob:顺便说一句,问题不是因为起订量返回值
0。库本身似乎存在一个问题,它无法使用设置索引器处理It.IsAny。我不知道为什么,但你可以尝试在他们的Github 上打开一个问题。
标签: c# moq indexed-properties