如何测试事件触发 [英] How to test events firing

查看:115
本文介绍了如何测试事件触发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在开始阅读之前,请注意,我已经包含了完整的示例的所有代码,因此可能很长. :D

Before you begin reading please note that I've included all of the code for a complete example so it might be long. :D

我目前正在使用Exchange Web服务(EWS)进行项目,该项目负责在新邮件到达指定邮箱时订阅EWS请求对特定事件进行回调.但是,过去几周来我们的电子邮件服务器一直存在问题.由于我们的实施与Exchange联机紧密耦合,因此我们无法继续工作.这是我想到创建一个可以与Exchange一起使用或不与Exchange一起使用的小型事件处理程序实现的想法.显然,如果没有Exchange在线,我将不得不手动引发事件.

I'm currently working on a project using Exchange Web Services (EWS) that is responsible for subscribing to EWS requesting callbacks to specific events whenever new mail arrives in specified mailboxes. However, we've been having issues with our email server for the few weeks. Since our implementation was so tightly coupled to Exchange being online we were not being able to continue work. This is when I had an idea of creating a small event handler implementation that could work with or without Exchange. Obviously, without Exchange being online I would have to manually raise events.

创建通用事件处理程序接口的理由是,我可以创建一个可以与Exchange一起使用或不与Exchange一起使用的事件处理程序类.因此,对于Exchange实现,我将使用IEventHander<>.对于虚拟实现,我将具有EventHandlerBase<NotificationEventArgs, DisconnectEventArgs, ErrorEventArgs>,这是我在下面显示的内容.而且,后者的所有EventArgs对象都是自定义的,没有任何功能.

My reasoning for creating a generic event handler interface is that I could create an event handler class that could work with or without Exchange. So for an Exchange implementation I'd have IEventHander<>. And for a dummy implementation I'd have EventHandlerBase<NotificationEventArgs, DisconnectEventArgs, ErrorEventArgs>, which is what I've shown below. Also, all EventArgs objects from the latter are custom with no functionality whatsoever.

请参阅下文,了解我到目前为止的情况.

See below what I have thus far.

public interface IEventHandler
    <TOnNotification, TOnDisconnect, TOnSubscriptionError>
    where TOnNotification : EventArgs
    where TOnDisconnect : EventArgs
    where TOnSubscriptionError : EventArgs
{
    event EventHandler<TOnNotification> OnNotification;
    event EventHandler<TOnDisconnect> OnDisconnect;
    event EventHandler<TOnSubscriptionError> OnSubscriptionError;

    void OnNotificationEvent(object sender, TOnNotification args);
    void OnDisconnectEvent(object sender, TOnDisconnect args);
    void OnErrorEvent(object sender, TOnSubscriptionError args);
}

public abstract class EventHandlerBase<TOnNotification, TOnDisconnect, TOnError>
    : IEventHandler<TOnNotification, TOnDisconnect, TOnError>
    where TOnNotification : EventArgs
    where TOnDisconnect : EventArgs
    where TOnError : EventArgs
{
    public event EventHandler<TOnNotification> OnNotification;
    public event EventHandler<TOnDisconnect> OnDisconnect;
    public event EventHandler<TOnError> OnSubscriptionError;

    public abstract void OnNotificationEvent(object sender, TOnNotification args);
    public abstract void OnDisconnectEvent(object sender, TOnDisconnect args);
    public abstract void OnErrorEvent(object sender, TOnError args);
}

public class DummyEventHandler : 
    EventHandlerBase<NotificationEventArgs, DisconnectEventArgs, ErrorEventArgs>
{
    public override void OnNotificationEvent(object sender, NotificationEventArgs args)
    {
        Console.WriteLine(MethodBase.GetCurrentMethod());
    }

    public override void OnDisconnectEvent(object sender, DisconnectEventArgs args)
    {
        Console.WriteLine(MethodBase.GetCurrentMethod());
    }

    public override void OnErrorEvent(object sender, ErrorEventArgs args)
    {
        Console.WriteLine(MethodBase.GetCurrentMethod());
    }
}

public interface ISubscriber
{
    void Subscribe();
    void Unsubcribe();
}

public class DummyStreamingNotificationSubscriber : ISubscriber
{
    private readonly IEventHandler<NotificationEventArgs, DisconnectEventArgs, ErrorEventArgs> _eventHandler;

    public DummyStreamingNotificationSubscriber(
        IEventHandler<NotificationEventArgs, DisconnectEventArgs, ErrorEventArgs> eventHandler)
    {
        _eventHandler = eventHandler;
    }

    public void Subscribe()
    {
        Console.WriteLine("Subscribing to streaming notification.");

        var streamingConnection = new DummyStreamingSubscriptionConnection();

        streamingConnection.OnNotification += _eventHandler.OnNotificationEvent;
        streamingConnection.OnDisconnect += _eventHandler.OnDisconnectEvent;
        streamingConnection.OnError += _eventHandler.OnErrorEvent;
    }

    public void Unsubcribe()
    {
        Console.WriteLine("Unsubscribing to streaming notification.");
    }
}

// Only used to mimic EWS' StreamingSubscriptionConnection class
public class DummyStreamingSubscriptionConnection
{
    public event EventHandler<NotificationEventArgs> OnNotification;
    public event EventHandler<DisconnectEventArgs> OnDisconnect;
    public event EventHandler<ErrorEventArgs> OnError;
}

// Mimics EWS' NotificationEventArgs class
public class NotificationEventArgs : EventArgs { }

// Mimics EWS' SubscriptionErrorEventArgs class
public class ErrorEventArgs : EventArgs { }

// Mimics EWS' SubscriptionErrorEventArgs class
public class DisconnectEventArgs : EventArgs { }

public class DummyService : IService
{
    private readonly ISubscriber _subscriber;

    public DummyService(ISubscriber subscriber)
    {
        _subscriber = subscriber;
    }   

    public void Start()
    {
        Console.WriteLine("Starting service.");

        _subscriber.Subscribe();
    }

    public void Stop()
    {
        Console.WriteLine("Stopping service.");

        _subscriber.Unsubcribe();
    }
}

最后,将它们粘合在一起.

And finally, glue it all together.

var service = new DummyService(
    new DummyStreamingNotificationSubscriber(
        new DummyEventHandler()));
service.Start();

ExchangeEventHandler类中,

OnNotificationEvent()提取电子邮件并使用它的地方.简而言之,我需要能够处理事件处理(例如,使用DI),以确保无论有没有Exchange,我仍然可以使用流式订阅服务.

In the ExchangeEventHandler class is where OnNotificationEvent() would fetch the email and work with it. In short, I need to be able stub out (e.g. with DI) the event handling to ensure I can still work with my streaming subscription service with or without Exchange.

我如何测试引发OnNotification事件实际上会调用适当的方法并执行其应做的事情(例如使用电子邮件).我假设嘲笑会发挥作用.本质上,我想确保一旦真正的服务实现在起作用,例如一旦事件OnNotification触发,它将实际上继续保持其正常运行.

How can I test that raising an OnNotification event will actually call the appropriate method and do what it's supposed to do (e.g. consume the email). I'm assuming mocking will come in play. Essentially, I want to ensure that once the real service implementation is in play that once for example event OnNotification fires it'll actually keep on running its course.

如果有不清楚的地方,请随时提出问题.我确实意识到这可能不是完美的解决方案,因此我也乐于接受不同的实施建议.

Please don't hesitate to ask question if something isn't clear. I do realize this might not be the perfect solution therefore I'm also open to different implementation suggestions.

推荐答案

要检查在引发事件或任何其他函数调用之后是否调用了approp方法,您将需要使用StrictMock和Mock引发该事件(我使用RhynoMocks).

To check whether approp method gets called after raising event or any other function call, you will need to use StrictMock and Mock raising that event (I use RhynoMocks).

您可能想要分离/分解要在执行代码中测试的功能.

you might want to separate out/ break down what functionality you want to test in your execution code.

如果要测试有关确保Event调用特定的X方法"的功能(并且只是为了测试它确实调用了该X方法),请在您的DummyEventHandler示例中,要确保调用Console.WriteLine(MethodBase.GetCurrentMethod())对吧?

If you want to test functionality around "making sure that Event calls particular X method" (and just to test it does call that X method), in your DummyEventHandler example, you want to make sure Console.WriteLine(MethodBase.GetCurrentMethod()) gets called right?

您可以使用RhynoMocks来做到这一点:

You can use RhynoMocks to do that:

var mocks = new MockRepository();

IEventHandler  eventHandler = MockRepository.GenerateStrictMock<IEventHandler>()

eventHandler.Expect( x => x.OnNotificationEvent(null, null).IgnoreArguments();
(do above for other methods)

然后:

var service = new DummyService(
      new DummyStreamingNotificationSubscriber(eventHandler)); 
service.Start();  

确保在您启动服务时,确保您的DummyStreamingSubscriptionConnection发布/调用事件

Make sure when you service starts, make sure your DummyStreamingSubscriptionConnection publishes/invokes the events

这篇关于如何测试事件触发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆