首页 / C# / 在C#中使用Moq提升复杂事件
在C#中使用Moq提升复杂事件
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了在C#中使用Moq提升复杂事件,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4589字,纯文字阅读大概需要7分钟。
内容图文
下面的代码应该是自解释的:我们有一个适配器,它使用来自传输(层)的事件,它包含MessageRegistrar(对象类型,因为我们无法告诉它的类型,基本上因为这是遗留代码:-)) .传输层具有混凝土,其具有事件.
我想测试事件被触发的情况,所以..
经过几个小时试图弄清楚为什么它不会通过,我提出了以下挑战:
[TestFixture]
public class AdaptorTests
{
public delegate void TracksEventHandler(object sender, List<int> trklst);
public class MyEventHolder
{
public virtual event TracksEventHandler EventName;
}
public interface ITransport
{
object MessageRegistrar { get; }
}
public class MyTransport : ITransport
{
private readonly MyEventHolder m_eventHolder;
public MyTransport(MyEventHolder eventHolder)
{
m_eventHolder = eventHolder;
}
public virtual object MessageRegistrar
{
get { return m_eventHolder; }
}
}
public class MyAdaptor
{
private readonly ITransport m_transport;
public MyAdaptor(ITransport transport)
{
EventTriggered = false;
m_transport = transport;
}
public void Connect()
{
MyEventHolder eventHolder = m_transport.MessageRegistrar as MyEventHolder;
if (eventHolder != null)
eventHolder.EventName += EventHolderOnEventName;
}
private void EventHolderOnEventName(object sender, List<int> trklst)
{
EventTriggered = true;
}
public bool EventTriggered { get; private set; }
}
[Test]
public void test1()
{
Mock<MyEventHolder> eventHolderMock = new Mock<MyEventHolder> {CallBase = true};
Mock<MyTransport> transportMock = new Mock<MyTransport>(eventHolderMock.Object) {CallBase = true};
MyAdaptor adaptor = new MyAdaptor(transportMock.Object);
adaptor.Connect();
MyEventHolder eventHolder = transportMock.Object.MessageRegistrar as MyEventHolder;
Mock.Get(eventHolder).Raise(eh => eh.EventName += null, new List<int>());
Assert.IsTrue(adaptor.EventTriggered);
}
[Test]
public void test2()
{
Mock<MyEventHolder> eventHolderMock = new Mock<MyEventHolder> { CallBase = true };
Mock<MyTransport> transportMock = new Mock<MyTransport>(eventHolderMock.Object) { CallBase = true };
MyAdaptor adaptor = new MyAdaptor(transportMock.Object);
adaptor.Connect();
MyEventHolder eventHolder = transportMock.Object.MessageRegistrar as MyEventHolder;
Mock.Get(eventHolder).Raise(eh => eh.EventName += null, null, new List<int>());
Assert.IsTrue(adaptor.EventTriggered);
}
}
我的问题是:为什么不通过测试(至少其中一个)?
编辑@ 151217-0822将’adaptor.Connect()’添加到原始帖子(仍然无法解决问题).
替代方法
积分给@Patrick Quirk:谢谢!
对于那些遇到同样问题的人:在我理解Patrick-Quirk检测到的内容并尝试了几个失败的解决方法之后,我最终添加了以下经过验证的修复:’eventHolder.FireEventNameForTestings(new List());’:
public class MyEventHolder
{
public virtual event TracksEventHandler EventName;
public virtual void FireEventNameForTestings(List<int> trklst)
{
TracksEventHandler handler = EventName;
if (handler != null)
handler(this, trklst);
}
}
[Test]
public void test3()
{
Mock<MyEventHolder> eventHolderMock = new Mock<MyEventHolder> { CallBase = true };
Mock<MyTransport> transportMock = new Mock<MyTransport>(eventHolderMock.Object) { CallBase = true };
MyAdaptor adaptor = new MyAdaptor(transportMock.Object);
adaptor.Connect();
MyEventHolder eventHolder = transportMock.Object.MessageRegistrar as MyEventHolder;
eventHolder.FireEventNameForTestings(new List<int>());
Assert.IsTrue(adaptor.EventTriggered);
}
HTH ..
解决方法:
似乎CallBase和Raise()有一个意想不到的(对我而言)交互.
当您将事件处理程序附加到模拟上的虚拟事件时,您将通过this code in Moq:
if (invocation.Method.IsEventAttach())
{
var delegateInstance = (Delegate)invocation.Arguments[0];
// TODO: validate we can get the event?
var eventInfo = this.GetEventFromName(invocation.Method.Name.Substring(4));
if (ctx.Mock.CallBase && !eventInfo.DeclaringType.IsInterface)
{
invocation.InvokeBase();
}
else if (delegateInstance != null)
{
ctx.AddEventHandler(eventInfo, (Delegate)invocation.Arguments[0]);
}
return InterceptionAction.Stop;
}
你可以看到,如果CallBase为true,那么它会将你的处理程序添加到具体对象的事件中(通过invocation.InvokeBase()).如果CallBase为false,它将把它添加到mock上的调用列表中(通过AddEventHandler).现在让我们看一下the code for Raise(),它从Expression中获取事件对象,然后调用DoRaise():
internal void DoRaise(EventInfo ev, EventArgs args)
{
// ... parameter validation
foreach (var del in this.Interceptor.InterceptionContext.GetInvocationList(ev).ToArray())
{
del.InvokePreserveStack(this.Object, args);
}
}
看看对GetInvocationList()的调用?它从我上面提到的模拟中检索调用列表.此代码从不调用基础对象上的实际事件.
因此,似乎没有办法在CallBase设置为true的模拟对象上引发事件.
我看到的唯一解决方法是,如果要求CallBase为true,则向您的具体MyEventHolder添加一个方法来触发您的事件.显然你发布的是一个简化的例子,所以我不能给你更多的指导,但希望我已经告诉你为什么你的东西不起作用.
内容总结
以上是互联网集市为您收集整理的在C#中使用Moq提升复杂事件全部内容,希望文章能够帮你解决在C#中使用Moq提升复杂事件所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。