【发布时间】:2011-08-22 23:07:36
【问题描述】:
我们有一个相当复杂的界面层次结构,我正在努力让 Moq 做我想做的事。
我有一个接口IReservation,它扩展了IRulesReservation,并用另一种类型的新实现隐藏了它的枚举器。
public interface IReservation : IRulesReservation
{
new IEnumerator<IRoutePart> GetEnumerator();
}
IRulesReservation 扩展IEnumerable。
public interface IRulesReservation : IEnumerable<IRulesRoutePart>
{
}
我尝试测试的方法采用IReservation,但在不同的点需要访问IEnumerable<IRulesRoutePart>。我的 Mock 设置如下:
m_mock = new Mock<IReservation>();
m_mock.As<IRulesReservation>().Setup(r => r.GetEnumerator()).Returns(routeParts.Select(rp => (IRulesRoutePart)rp).GetEnumerator());
在示例中,routeParts 是来自Mock<IRouteParts> 对象的IRouteParts 列表,这些对象使用.As<IRulesRoutePart>() 设置。
每当我在我正在测试的函数中遇到一些使用枚举器的代码时,它就会跳过迭代,就好像集合是空的一样。
我的设置有问题吗?还是 Moq 只是无法处理以这种方式隐藏的枚举器?
编辑:我刚刚在 mock 上运行测试代码时注意到的一些奇怪行为:
Assert.That((reservation.Object as IRulesReservation).Count() == 8);
Assert.That((reservation.Object as IEnumerable<IRulesRoutePart>).Count() == 8);
第一行会通过,但第二行会失败。
我尝试更改模拟以专门为IEnumerable<IRulesRoutePart> 设置一个枚举器,但没有效果:
m_mock.As<IEnumerable<IRulesRoutePart>>().Setup(r => r.GetEnumerator()).Returns(routeParts.Select(rp => (IRulesRoutePart)rp).GetEnumerator());
【问题讨论】:
-
你有没有发现任何其他信息?我遇到了同样的问题并试图解决它。
-
@poindexter12 - 我从来没有设法解决这个问题,但我们后来发现 Moq 会缓存你第一次调用模拟 GetEnumerator() 时获得的枚举器。这意味着后续调用将返回相同的枚举器,这可能是我在后续调用中得到不同行为的原因。要解决此问题,您可以模拟 GetEnumerator() 以返回创建新 Enumerator 的匿名方法,而不是像上面的示例代码中那样直接调用 GetEnumerator() 的具体实现。祝你好运!