[英]Mocking an abstract class that inherits from IEnumerable<T>
我正在尝试从我正在使用的库中模拟一个抽象类。 我没有访问源代码,只有反编译版本:
public abstract class Event : IEnumerable<Message>, IEnumerable
{
protected Event();
public abstract bool IsValid { get; }
public IEnumerator<Message> GetEnumerator();
public IEnumerable<Message> GetMessages();
}
这个反编译的代码让我感到困惑。 首先,冗余继承,也没有非抽象方法的实现,例如GetEnumerator
或IEnumerable.GetEnumerator()
。 但是它已编译,并且它可以工作,所以我认为它只是反编译的一个人工制品(如果这甚至是一件事?)
我尝试了以下模拟,它编译并运行而不抛出异常。
public static Event GetMockedEvent()
{
var mock = new Mock<Event>();
mock.Setup(e => e.IsValid).Returns(true);
mock.As<IEnumerable>().Setup(e => e.GetEnumerator()).Returns(MessageList());
return mock.Object;
}
private static IEnumerator<Message> MessageList()
{
yield return GetMockedMessage();
yield return GetMockedMessage();
}
private static Message GetMockedMessage()
{
var mock = new Mock<Message>();
// Unimportant setups...
return mock.Object;
}
但是我没有得到模拟对象中的任何元素,我按以下方式测试
var ev = GetMockedEvent();
foreach (var msg in ev)
{
//
}
但是枚举是空的,我无法弄清楚原因。 我已经在这个问题上摸不着头脑了一整天,所以我非常感谢你的帮助。
亲切的问候
当你foreach
一个序列,IIRC编译器会desugar,要到通用版的调用GetEnumerator
,所以这是你必须嘲笑之一。
虽然我没有尝试过,但这样的事情可能会成功。
public static Event GetMockedEvent()
{
var mock = new Mock<Event>();
mock.Setup(e => e.IsValid).Returns(true);
mock.As<IEnumerable<Message>>()
.Setup(e => e.GetEnumerator())
.Returns(() => MessageList());
return mock.Object;
}
Event
有三个公共成员(以及一个显式实现的接口方法)。 你已经嘲笑了其中两个,然后编写了使用第三个的测试代码。 如果你想让它在你的测试代码中返回一些东西,你需要实际模拟GetEnumerator
实现(当然你也应该模拟非泛型版本,以防其他一些测试代码试图使用它)。
前言您粘贴的Event
类的代码只是元数据表示。 如果你真的想看到它的源代码,请使用完整的反编译器,如ILSpy ( VS扩展 )。 结束前言
Event
类as-is无法完全模拟,因为GetEnumerator
不是虚拟的(至少就你的代码片段而言),所以
由于该类隐式实现IEnumerable<Message>
,因此foreach
循环直接调用声明的方法,而不是您在GetMockedEvent
方法中设置的“显式实现”。
要清楚,下面是我试图运行的完整代码段。 我决定将NotImplementedException
作为未知方法体的“中性”替换。
void Main()
{
var ev = GetMockedEvent();
foreach (var msg in ev)
{
Console.WriteLine(msg);
}
}
public abstract class Event : IEnumerable<Message>, IEnumerable
{
protected Event() { }
public abstract bool IsValid { get; }
public IEnumerator<Message> GetEnumerator() { throw new NotImplementedException(); }
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public IEnumerable<Message> GetMessages() { throw new NotImplementedException(); }
}
public class Message { }
public static Event GetMockedEvent()
{
var mock = new Mock<Event>();
mock.Setup(e => e.IsValid).Returns(true);
mock.As<IEnumerable<Message>>().Setup(e => e.GetEnumerator()).Returns(MessageList());
// The next line doesn't work either because the method is not virtual
//mock.Setup(e => e.GetEnumerator()).Returns(MessageList());
return mock.Object;
}
private static IEnumerator<Message> MessageList()
{
yield return GetMockedMessage();
yield return GetMockedMessage();
}
private static Message GetMockedMessage()
{
var mock = new Mock<Message>();
// Unimportant setups...
return mock.Object;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.