我正在尝试从我正在使用的库中模拟一个抽象类。我无权访问源代码,只能访问反编译版本:
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)
{
//
}
但枚举是空的,我无法弄清楚原因。我已经对这个问题感到头疼了整整一天,所以我非常感谢你的帮助。
亲切的问候
答案 0 :(得分:3)
当您foreach
超过一个序列时,IIRC编译器会将其视为对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;
}
答案 1 :(得分:2)
Event
有三个公共成员(以及一个明确实现的接口方法)。你已经嘲笑了其中两个,然后编写了使用第三个的测试代码。如果你希望它在你的测试代码中返回一些东西,你需要实际模拟GetEnumerator
实现(当然你也应该模拟非泛型版本,以防其他一些测试代码试图使用它)。
答案 2 :(得分:2)
前言 您粘贴的Event
类的代码只是元数据表示形式。如果您真的想查看其源代码,请使用完整的反编译器,例如ILSpy(VS extension)。 结束前言
Event
类不能完全嘲笑,因为GetEnumerator
不是虚拟的(至少就你的代码片段而言),所以
由于类隐式实现IEnumerable<Message>
,foreach
循环直接调用声明的方法,而不是&#34;显式实现&#34;您使用GetMockedEvent
方法进行设置。
要清楚,下面是我试图运行的完整代码段。我决定抛出NotImplementedException
作为&#34;中立&#34;替换未知的方法体。
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;
}