Sve*_*ann 4 c# ienumerable moq
我正在尝试模拟Visual Studio CommandBars实例.CommandBars实现非通用的IEnumerable接口.为了能够迭代模拟,我设置了GetEnumerable().奇怪的是,这只有在我将mock.Object作为CommandBars的一个实例访问时才有效.如果我转换为IEnumerable(因为它在使用Linq方法时隐式发生),GetEnumerable()突然返回null.有人可以解释这种行为吗?
var mockCommandBars = new Mock<CommandBars>();
IEnumerable bars = new List<CommandBar>();
mockCommandBars.Setup(cb => cb.GetEnumerator()).Returns(bars.GetEnumerator);
var cbs = mockCommandBars.Object;
var cbs1 = cbs.GetEnumerator(); // returns instance
var ecbs = (IEnumerable) cbs;
var cbs2 = ecbs.GetEnumerator(); // returns null!
Run Code Online (Sandbox Code Playgroud)
编辑:我正在使用Moq 4.2.1402.2112
通过检查实际的类型
var cbs = mockCommandBars.Object;
Run Code Online (Sandbox Code Playgroud)
在运行时,似乎cbs已被包装为:
cbs {Castle.Proxies.CommandBarsProxy}
Run Code Online (Sandbox Code Playgroud)
并且演员表会IEnumerable干扰代理人的行为.
您可以在此处使用此帖子中的帮助方法来连接代理的__target属性,例如
var cbs2 = UnwrapProxy<IEnumerator>(cbs.GetEnumerator());
Run Code Online (Sandbox Code Playgroud)
哪里
internal static TType UnwrapProxy<TType>(TType proxy)
{
try
{
dynamic dynamicProxy = proxy;
return dynamicProxy.__target;
}
catch (RuntimeBinderException)
{
return proxy;
}
}
Run Code Online (Sandbox Code Playgroud)
编辑
从这里可以清楚地看到,设置没有在底层_CommandBars.IEnumerable接口上执行
您可以明确更改设置:
var cbs = mockCommandBars.As<_CommandBars>().As<IEnumerable>();
cbs.Setup(cb => cb.GetEnumerator()).Returns(bars.GetEnumerator());
var ecbs = (IEnumerable)cbs.Object; // The cast is now redundant.
var cbs2 = ecbs.GetEnumerator();
Run Code Online (Sandbox Code Playgroud)
如果你想保留一个模拟变量来传递,你可以像这样设置它.
var mockCommandBars = new Mock<CommandBars>();
mockCommandBars.Setup(cb => cb.GetEnumerator()).Returns(bars.GetEnumerator);
mockCommandBars.As<IEnumerable>().Setup(cb => cb.GetEnumerator()).Returns(bars.GetEnumerator);
Run Code Online (Sandbox Code Playgroud)
这告诉Moq Mock实现了两个接口,并且GetEnumerator两者都是独立定义的.