c# - 将目标强制转换为 IEnumerable 时,莫清 GetEnumerable 失败

标签 c# moq ienumerable

我正在尝试模拟 Visual Studio CommandBars实例。 CommandBars 实现非通用 IEnumerable 接口(interface)。为了能够迭代模拟,我设置了 GetEnumerable()。奇怪的是,只有当我将mock.Object作为CommandBars的实例访问时,这才有效。如果我将 is 转换为 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!

编辑:我使用的是 Moq 4.2.1402.2112

最佳答案

通过检查实际类型

 var cbs = mockCommandBars.Object;

在运行时,cbs 似乎已被包装为:

 cbs    {Castle.Proxies.CommandBarsProxy}

并且转换为 IEnumerable 会干扰代理的行为。

您也许可以使用此 post here 中的辅助方法,连接对代理的 __target 属性的访问,例如

var cbs2 = UnwrapProxy<IEnumerator>(cbs.GetEnumerator());

哪里

  internal static TType UnwrapProxy<TType>(TType proxy)
  {
     try
     {
        dynamic dynamicProxy = proxy;
        return dynamicProxy.__target;
     }
     catch (RuntimeBinderException)
     {
        return proxy;
     }
  }

编辑

From Here很明显,该设置并未在底层 _CommandBars.IEnumerable 接口(interface)

上执行

您可以显式更改设置:

     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();
<小时/>

如果你想保留一个模拟变量来传递,你可以这样设置。

var mockCommandBars = new Mock<CommandBars>();
mockCommandBars.Setup(cb => cb.GetEnumerator()).Returns(bars.GetEnumerator);
mockCommandBars.As<IEnumerable>().Setup(cb => cb.GetEnumerator()).Returns(bars.GetEnumerator);

这告诉 Moq,Mock 实现了这两个接口(interface),并为这两个接口(interface)独立定义了 GetEnumerator

关于c# - 将目标强制转换为 IEnumerable 时,莫清 GetEnumerable 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23885665/

相关文章:

c# - 最小起订量 + 单元测试 - System.Reflection.TargetParameterCountException : Parameter count mismatch

c# - 具有多个约束的单个泛型参数的 Moq 方法

c# - 使用通用工作单元 C# 模拟通用存储库

c# - 枚举前的 "~"是什么意思

c# - 基础设施 UltraGrid : GroupBy row ForeColor changes when clicked

c# - 如何使用NEST删除特定的河流?

c# - 使用最小起订量从属性返回真实对象

c# - 如何实现通用 IEnumerable 或 IDictionary 以避免 CA1006?

c# - 为什么 IEnumerator<T> 会影响 IEnumerable<T> 的状态,即使 ienumerator 从未到达终点?

c# - 查找 IEnumerable 的第一个索引