Как проверить стрельбу событий - PullRequest
1 голос
/ 08 апреля 2011

Прежде чем вы начнете читать, обратите внимание, что я включил весь код для полного примера, поэтому он может быть длинным.: D

Проблема

В настоящее время я работаю над проектом с использованием веб-служб Exchange (EWS), который отвечает за подписку на EWS, запрашивающую обратные вызовы для определенных событий всякий раз, когда в указанные почтовые ящики поступает новая почта.Однако у нас были проблемы с нашим почтовым сервером в течение нескольких недель.Поскольку наша реализация была так тесно связана с подключением Exchange к сети, мы не смогли продолжить работу.Именно тогда у меня появилась идея создать небольшую реализацию обработчика событий, которая могла бы работать с или без Exchange.Очевидно, что если бы Exchange не был в сети, мне пришлось бы вручную вызывать события.

Моя причина создания универсального интерфейса обработчика событий заключается в том, что я мог бы создать класс обработчика событий, который мог бы работать с Exchange или без него.Так что для реализации Exchange у меня будет IEventHander<>.И для фиктивной реализации у меня будет EventHandlerBase<NotificationEventArgs, DisconnectEventArgs, ErrorEventArgs>, что я и показал ниже.Кроме того, все объекты EventArgs из последнего являются пользовательскими без какой-либо функциональности.

См. Ниже то, что я имею до сих пор.

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();
    }
}

И, наконец, склеиваем все это вместе.

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

В классе ExchangeEventHandler OnNotificationEvent() будет получать электронную почту и работать с ней.Короче говоря, мне нужно иметь возможность заглушить (например, с помощью DI) обработку событий, чтобы гарантировать, что я все еще могу работать со своей службой потоковой подписки с или без Exchange.

Вопрос

Как я могупроверьте, что вызов события OnNotification на самом деле вызовет соответствующий метод и сделает то, что должен (например, использует электронную почту).Я предполагаю, что насмешка придет в игру.По сути, я хочу убедиться, что после того, как будет реализована реальная реализация сервиса, когда однажды, например, событие OnNotification сработает, оно действительно продолжит работу.

Пожалуйста, не стесняйтесь задавать вопрос, если что-тоне понятноЯ понимаю, что это может быть не идеальное решение, поэтому я также открыт для различных предложений по реализации.

1 Ответ

3 голосов
/ 08 апреля 2011

Чтобы проверить, вызывается ли метод Approp после вызова события или любого другого вызова функции, вам нужно использовать StrictMock и Mock для вызова этого события (я использую RhynoMocks).

вы можете отделить / разбить, какую функциональность вы хотите проверить в своем коде выполнения.

Если вы хотите проверить работоспособность вокруг «проверки того, что Event вызывает определенный метод X» (и просто для проверки, что он вызывает этот метод X), в вашем примере DummyEventHandler вы хотите убедиться, что Console.WriteLine(MethodBase.GetCurrentMethod()) Вам звонят правильно?

Вы можете использовать RhynoMocks для этого:

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 публикует / вызывает события

...