• Noser.com
facebook
linkedin
twitter
youtube
  • NOSERmobile
    • Android
    • HTML 5
    • Hybrid Apps
    • iOS
    • Windows Phone
  • NOSERembedded
    • Medizintechnik
  • NOSERprojektmanagement
  • NOSERtesting
  • NOSERlifecycle
    • .NET Allgemein
    • Application Lifecylce Management
    • Apps
    • Architektur
    • ASP.NET
    • Azure
    • Cleancode
    • Cloud
    • Silverlight
    • Visual Studio / Team Foundation Server
    • Windows 8
    • Windows Presentation Foundation
  • NOSERinnovation
    • Big Data
    • Cloud
    • IoT
    • Operations Research
    • Augmented Reality
    • RFID, NFC, Bluetooth LE

How you can unit test a subscription for a Prism event

11. November 2016
Roger Huber
0
.NET, C#, Moq, Prism

The project that I’m currently participating in is using Prism’s event mechanism. It allows communication between loosly coupled components by means of events. This article is about how you can unit test event handlers for such Prism events. First of all, here is a subscriber that subscribes for the ChildAddedEvent:

public SubjectUnderTest(IEventAggregator eventAggregator)
{
  eventAggregator.GetEvent<ChildAddedEvent>().Subscribe(OnChildAdded);
}

private void OnChildAdded(ChildAddedEvent evt)
{
  int var = 0;
}

Crucial question

How can you now unit test this private OnChildAdded method?

My personal basic condition when writing a unit test is that every custom type used by subject under test is mocked. That way, the test coverage metrics get more valueable and the unit test is used for the purpose it is intended for.

A first attempt

You could call OnChildAdded in the unit test by means of PrivateObject class (Microsoft.VisualStudio.TestTools.UnitTesting):

// Act
PrivateObject exposedSubjectUnderTest = new PrivateObject(subjectUnderTest);
exposedSubjectUnderTest.Invoke("OnChildAdded", childAddedEvent);

However, let’s look for a better idea because the main issue here is that the “glue” between the subscription and the handler is not tested:

greenunittest
By the way, the green markers are comming from NCrunch and denotes the lines that are covered by only passing unit tests. There are other colors too: Red means that the line is covered but there is at least one failing unit test. Black marks a line not coverred by any unit test.

A better solution

Therefore I implemented the static EventHelper.SetupEventSubscription method that can be used in our unit tests. The key pieces are the callback parameter of type Action<Action<T>> and Moq’s Callback method. The type Action<Action<T>> is required because we want to make the delegate be available in the unit test for execution and an out parameter can’t be used inside a lambda expression.

public static void SetupEventSubscription<T>(IEventAggregator eventAggregator, out T evt, Action<Action<T>> callback) where T : PubSubEvent<T>, new()
{
  evt = Mock.Of<T>();
  SetupEventCallback(eventAggregator, evt, callback);
}

private static void SetupEventCallback<T>(IEventAggregator eventAggregator, T evt, Action<Action<T>> callback) where T : PubSubEvent<T>, new()
{
  Mock.Get(eventAggregator).Setup(m => m.GetEvent<T>()).Returns(evt);
  Mock.Get(evt)
  .Setup(m => m.Subscribe(It.IsAny<Action<T>>(), It.IsAny<ThreadOption>(), It.IsAny<bool>(), It.IsAny<Predicate<T>>()))
    .Callback<Action<T>, ThreadOption, bool, Predicate<T>>((eventHandler, x, y, z) => callback(eventHandler));
}

Then, SetupEventSubscription method can be used like it is shown in the following code snippet. The code also shows a good use of PrivateObject: I used it in the SetChild extension method (line 11) for setting one of ChildAddedEvent’s private fields. Of course, SetChild is only visible in the unit tests.

// Arrange
ChildAddedEvent childAddedEvent;
Action<ChildAddedEvent> childAddedEventHandler = null;

var eventAggregator = Mock.Of<IEventAggregator>();
EventHelper.SetupEventSubscription(eventAggregator, out childAddedEvent, childAddedEventHandler);

var subjectUnderTest = new SubjectUnderTest(eventAggregator);

var child = Mock.Of<IChild>();
childAddedEvent.SetChild(child)

// Act
childAddedEventHandler(childAddedEvent);

If somebody now removes the subscription, the unit test will fail. In addition, a renaming of the handler will also not require to update any unit test.

Failing unit test

 

Tag Cloud

.NET android Angular AngularJs app Arduino ASP.Net automated testing Azure Big Data C# C++ Cloud continuous integration Elm Embedded gRPC Internet of Things IoT Java Javascript M2M OWASP Projektmanagement protobuf Python Raspberry Pi Reactive Programming REST Scrum Security Softwarequalität SPA Testen testing Testmanagement Teststrategie Visual Studio WebAPI windows WPF Xamarin Xamarin.Android Xamarin.Forms Xamarin.iOS

Archive

Current Posts

  • Virtual pty/tty uart listener: Pitfalls on linux socat
  • Akzente setzen mit der Android Splash Screen API unter .NET MAUI
  • Do You have Your Personal Space?
  • Automated provisioning with ARM Templates
  • Asynchrone Beobachtungen und Versprechungen in Angular

Last Comments

  • Hans Reinsch bei Der Safety-Plan: Die wichtigsten Antworten mit Checkliste
  • George H. Barbehenn bei Modeling Optocouplers with Spice
  • Noser Blog Touch-Actions in Xamarin.Forms - Noser Blog bei Mach mehr aus Animationen in Xamarin.Forms mit SkiaSharp
  • Noser Blog Focus on the Secure Storage service of Trusted Firmware (TFM) - Noser Blog bei First run of the Trusted Firmware (TFM) application
  • Noser Blog First run of the Trusted Firmware (TFM) application - Noser Blog bei Focus on the Secure Storage service of Trusted Firmware (TFM)

Popular Posts

Xamarin.Android Code Obfuscation

6 Comments

ManuScripts: Wenn jemand eine Reise tut... Funktionale Programmierung mit Elm - Teil 1 - Aufbruch

5 Comments

ManuScripts: Wenn jemand eine Reise tut... Funktionale Programmierung mit Elm - Teil 2 - Kein Picknick

4 Comments

Contact us

  1. Name *
    * Please enter your name
  2. Email *
    * Please enter a valid email address
  3. Message *
    * Please enter message
© 2013 NOSER ENGINEERING AG. All rights reserved. Datenschutz | Cookie-Richtlinie