Skip to content

A helper library for writing unit tests with Prism's EventAggregator

License

Notifications You must be signed in to change notification settings

kristofberge/EventAggregator_Mocker

Repository files navigation

EventAggregator_Mocker

EventAggregator_Mocker is a helper library for writing unit tests with Prism's EventAggregator and Moq. It allows you to verify that an event has been published with the correct parameters and that it was handled in the correct way.

NuGet package

You'll get extension methods for Mock<IEventAggregator> and Mock<TEvent> (where TEvent extends PubSubEvent or PubSubEvent<T>)

How to use

In your unit test setup instantiate a mock of IEventAggregator.

var eventAggregatorMock = new Mock<IEventAggregator>();

Verifying that .Publish() is actually called on the event

Call one of the extension methods on the IEventAggregator and store the returned mocked event in a variable.

Without parameter:

Mock<MyEvent> mockedEvent = eventAggregatorMock.RegisterNewMockedEvent<MyEvent>();
...
mockedEvent.Verify(evt => evt.Publish(), Times.Once);

With paramater:

Mock<MyParamEvent> mockedParamEvent = eventAggregatorMock.RegisterNewMockedEvent<MyParamEvent, MyParam>();
...
mockedParamEvent.Verify(evt => evt.Publish(It.IsAny<MyParam>()), Times.Once);

Verifying the event handling behavior

We need to get a reference to the event handler, so we can invoke it manually and verify its behavior. We do this by storing this reference in a variable of type Action or Action<T>. The 2 extension methods I used above return an object of type Mock<TEvent>. On this object, we call another extension method SetSubscribeCallback<TEvent>(Action<Action> onSubscribe). This method takes an Action as a paramater that will recieve a reference to the event handler that will be passed in the Subscribe method of the actual code we're testing. So at this point we can store this reference in a variable and invoke it in our unit test. This works even if the method passed is private. If this sounds a bit complicated, here's an example:

Without parameter:

Action onEventPublishedAction; // This will keep a reference of the event handler that our production code passes into Subscribe().
// During setup
eventAggregatorMock
    .RegisterNewMockedEvent<MyEvent>()
    .SetSubscribeCallback<MyEvent>(action => onEventPublishedAction = action);
...
// In the unit test
onEventPublishedAction.Invoke();

// Verify that the code has run correctly

With parameter:

Action<MyParam> onEventPublishedAction;
// During setup
eventAggregatorMock
    .RegisterNewMockedEvent<MyEvent, MyParam>()
    .SetSubscribeCallback<MyEvent, MyParam>(action => onEventPublishedAction = action);
...
// In the unit test
onEventPublishedAction.Invoke(new MyParam());

// Perform assertions

To see it in action, check out this working example

Optional parameters

Since version 1.0 EventAggregator_Mocker supports all optional parameters of IEventAggragator.Subscribe().

For example:

eventAggregatorMock
    .RegisterNewMockedEvent<MyEvent>()
    .SetSubscribeCallback(
        action => receivedAction = action,
        ThreadOption.BackgroundThread,  // ThreadOption
        true  // keepSubscriberReferenceAlive
    );

About

A helper library for writing unit tests with Prism's EventAggregator

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages