.NET and me Coding dreams since 1998!

18Apr/093

Prism (CAL) unit testing – How to test Prism (CAL) Event Aggregator using Rhino Mocks

I spent some time recently working with Microsoft Composite Application Guidance (A.K.A. "Prism", “CAL”) and I think it is very good platform for building composite UI by either using WPF or Silverlight.

One of its greatest advantages is that it was done in open source manner which resulted with most of the community feedback being incorporated into lightweight, testing friendly framework. Reference implementation and samples are also good but showing only static stubs based testing which is ok but not as powerful as mocking with some mocking framework.

My mocking framework of choice is Rhino Mocks and I am going to make couple of simple blog posts showing how to test Prism code using the Rhino Mocks in couple of typical every day scenarios.

And that leads us to today’s blog post…

How to test Prism (CAL) EventAggregator based code using Rhino Mocks?

imageSUT I’ll be using today will be as simple as possible to deliver the message.

LoggingService is service which is responsible for handling the logging of system errors in a way that:

  • subscribes to system wide events which are requested to be logged without referencing the event sources
  • decides if event needs to be published (based on severity)
  • if it does, it formats the system event adding the time stamp etc
  • calls the publishing service which is handling the publishing of formatted event

Considering the fact that in my sample we would be having various publishing services in system publishing to different targets(eventlog, flat text file) the LoggingService gets dependency injected only a component implementing the IPublishingService.

Subscription to system wide events on a decoupled manner is possible through EventAggregator design pattern  which implementation is in Prism provided through IEventAggregator service.

The LogErrorEvent is an event to which LoggerService would subscribe and which carries the event argument of EventData type containing the ErrorLevel and ErrorMessage data.

Show me the code

Enough of my blabbering (and my English), code will speak for itself much better :)

Sample used in today's blog post can be downloaded here.

LoggingService

using System;
using System.Text;
using Microsoft.Practices.Composite.Events;

namespace Example
{
    public class LoggingService
    {
        private readonly IEventAggregator eventAggregator;
        private readonly IPublishingService publishingService;

        public LoggingService(IEventAggregator eventAggregator, IPublishingService publishingService)
        {
            this.eventAggregator = eventAggregator;
            this.publishingService = publishingService;
            this.eventAggregator
                .GetEvent<LogErrorEvent>()
                .Subscribe(this.LogIt);
        }

        private void LogIt(EventData eventData)
        {
            if (eventData.ErrorLevel<=100)
                return;

            var stringBuilder = new StringBuilder();
            stringBuilder
                .AppendFormat("Date:{0}", DateTime.Now)
                .AppendLine()
                .Append(eventData.ErrorMessage)
                .AppendLine();
            this.publishingService.PublishError(stringBuilder.ToString());
        }
    }
}

Nothing fancy there:

  • constructor accepts two parameters which provide to LoggingService access to event aggregator and publishing service through inversion of controls.
  • in constructor injected event aggregator is used for subscribing of LogIt method to LogErrorEvent.
  • LogIt method is private (wouldn’t work in case of Silverlight – but that is sepa rate blog post) and does next things:
    • makes sure that only events with level greater then 100 get published
    • formats the given error message into appropriate format
    • pass the formatted message to publishing service

 

IPublishingService, LogErrorEvent and EventData

namespace Example
{
    public interface IPublishingService
    {
        void PublishError(string errorMessage);
    }
}

using Microsoft.Practices.Composite.Presentation.Events;

namespace Example
{
    public class LogErrorEvent : CompositePresentationEvent
    {
        
    }
}

namespace Example
{
    public class EventData
    {
        public int ErrorLevel { get; set; }
        public string ErrorMessage { get; set; }
    }
}

No need to waste time commenting this…

Testing the code

I could have done test first etc, but I believe that it would obfuscate the point of this blog , which now once we see the code being tested is going to be just showing the tests 

Test 1 – How to make sure that event is getting subscribed

        /// 
        /// Shows how to verify that event aggregator subscription occurred.
        ///
        [TestMethod()]
        public void Ctor_Default_WouldSubscribeToLogErrorEvent()
        {
            // arrange
            var publishingServiceStub = MockRepository.GenerateStub<IPublishingService>();
            var eventAggregatorMock = MockRepository.GenerateStub<IEventAggregator>();
            var logErrorEvent = MockRepository.GenerateMock<LogErrorEvent>();

            // event aggregator get event would return mocked log error event 
            eventAggregatorMock.Stub(p => p.GetEvent<LogErrorEvent>()).Return(logErrorEvent);
            
            // expect that LogErrorEvent would be subscribed in constructor
            logErrorEvent
                .Expect(p => p.Subscribe(null))
                .Return(null)
                .IgnoreArguments() // we don't care which exact method or action subscribed, just that there was some.
                .Repeat.Once();

            // act
            var loggingService = new LoggingService(eventAggregatorMock, publishingServiceStub);

            // assert
            logErrorEvent.VerifyAllExpectations();
        }

The test is using Rhino Mocks AAA syntax introduced in 3.5 version (if you don’t know it, read Rhino Mocks Documentation Wiki excellent documentation).

In Arange section test:

  • defines two stubs for the services being used (stubs because I don’t care to set any expectation related to them in this test)
  • defines the mock of the event which subscription I am about to check
  • stubs the event aggregator behavior so on GetEvent<LoggErrorEvent>() method call would return event mock I created.
  • defines expectation on that event mock that subscription would occur once (IgnoreArguments() is there because this test doesn’t care really which method exactly would subscribe to event. Test cares only that subscription had occurred)

In Act section test just constructs the service

In Assert section test triggers verifying of the event log expectations (which in this test were: someone subscribed to this event)

(Note that making test for verifying that the Publish have occurred during the test would be pretty much the same as this test with a change on mocked expectations only)

Test 2a – How to invoke event aggregator in Act test section

Sometimes there is a behavior we want to unit test which is occurring upon the event being published through IEventAggregator and because we can be using anonymous delegate, private method handling the event (case of this blog post) there is no easy way to invoke functionality which is wanted to be tested.

This test shows how to invoke event aggregator to publish the desired event which would trigger code being tested,

In case of this example we want to test that not severe errors (error level <= 100) are not getting published.

        /// 
        /// An example of how to trigger event aggregator in act section
        ///
        [TestMethod()]
        public void LogIt_ErrorLevel100_WouldNotBePublished()
        {
            // arrange
            var logErrorEvent = new LogErrorEvent();
            var publishingServiceMock = MockRepository.GenerateMock<IPublishingService>();
            var eventAggregatorStub = MockRepository.GenerateStub<IEventAggregator>();

            eventAggregatorStub.Stub(p => p.GetEvent<LogErrorEvent>()).Return(logErrorEvent);
            
            // expect that publishing service would never be called
            publishingServiceMock
                .Expect(p => p.PublishError(Arg<string>.Is.Anything))
                .Repeat.Never();
            
            // act
            var loggingService = new LoggingService(eventAggregatorStub, publishingServiceMock);
            
            // invoke the event aggregator
            logErrorEvent.Publish(new EventData()
            {
                ErrorLevel = 100,
                ErrorMessage = "Some error message"
            });

           // assert
            publishingServiceMock.VerifyAllExpectations();
        }

In this test, test is having in Arrange section:

  • An instance of the log error event (not the mock of that event like in the case of previous test example)
  • Mock of the publishing service (in previous test we had stub) because that is service we need to check it won’t be called.
  • Stub of the event aggregator with stubbed GetEvent<LogErrorEvent> method
  • An expectation that PublishError method of the publishing service would never be called (regardless of the parameter being sent to that method)

In Act section test is :

  • constructing the logging service injecting the event aggregator stub and mock of publishing service
  • invoking the Publish method on a log error event instance passing the test data (error level == 100 in this test)

In Assert section, we are just triggering checking of expectation defined on mock of the publishing service (no call made to publish error method)

Test 2b – How to invoke event aggregator in Act test section

Although from perspective of this blog post it doesn’t have a lot of value here’s the test testing that publishing service will be called in case event will be published with error level greater then 100. (The more Rhino Mocks examples we have on web, the better adopting rate will be :))

	/// 
        /// An example of how to trigger event aggregator in act section
        ///
        [TestMethod()]
        public void LogIt_ErrorLevelGreaterThen100_WouldBePublished()
        {
            // arrange
            var logErrorEvent = new LogErrorEvent();
            var publishingServiceMock = MockRepository.GenerateMock<IPublishingService>();
            var eventAggregatorStub = MockRepository.GenerateStub<IEventAggregator>();

            eventAggregatorStub.Stub(p => p.GetEvent<LogErrorEvent>()).Return(logErrorEvent);

            publishingServiceMock
                .Expect(p => p.PublishError(Arg<string>.Matches(param => param.Contains("Some error message"))))
                .Repeat.Once();

            // act
            var loggingService = new LoggingService(eventAggregatorStub, publishingServiceMock);
            logErrorEvent.Publish(new EventData()
            {
                ErrorLevel = 101,
                ErrorMessage = "Some error message"
            });
            // assert
            publishingServiceMock.VerifyAllExpectations();
        }

Almost the same sample like previous one just with two small differences:

  • In arrange section, expectation is that the PublishError method would be called once with a method parameter containing “Some error message” string (inline constrains)
  • In act section, event is published with error level >100 to trigger the positive case when publishing service is been triggered

Green is nice :)

image

Conclusion

Thanks to P&P team and community feedback, CALPRISM event aggregator is implemented in such a way that mocking it is very easy (if not trivial) and every framework enabling easy testing is a good framework for me :) Good work P&P!

Filed under: Uncategorized 3 Comments
4Apr/091

Microsoft Unity Auto Mocking Container?


How to build Microsoft Unity Auto Mocking container in less then 20 minutes of work…


I have written before in detail about Auto Mocking Containers so I’ll skip here details on what is it etc and jump to the main point of this post: implementation of auto mocking container for Microsoft Unity.


Faced with PIA caused by constant explicit mocking of constructor dependencies (some of them not even used in my tests), I’ve tried to Google my way out by searching for Unity AMC on Codeplex, Google code etc. To my surprise that didn’t went well with best match being Roy Osherove Unity AMC container blog post which is just a nice fluent interface allowing explicit mock creation and injection on easier way. In other words, nothing automatic happening there at least not in a sense I needed it for my tests.


I started looking for the Object builder documentation and found some for version one scattered on couple of sites. The only thing I get from that documentation was that ObjectBuilder is one complex thing and “patching it” was far away from my end design goal: quick solution.


So, once I realized that I can not solve this on ninja way I tried “brute force” approach and in 20 minutes I had working Unity AMC.


The idea is simple:



  • create a class specializing the UnityContainer - “AutoMockingUnityContainer”

  • override UnityContainer “Get” methods

  • wrap in try catch block every “Resolve” call

  • if ResolutionFailedException would occur using reflection find greediest constructor (with the most parameters)

  • if no constructor info available, return a mock

  • try to resolve those parameters by using AMC resolve method

  • recourse until you won’t have complete set of arguments needed (real or mocked instances) for constructing the originally requested instance

Code explaining the above mentioned concepts is even simpler so let cut the chase and  save you from pain caused by reading more text written with “my English” ..




“Show me the code”


Imagine we would have a console application which is giving the answer on the meaning of the life

using System;
using Microsoft.Practices.Unity;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
var user = container.Resolve<User>();
Console.WriteLine(user.WhatIsTheMeaningOfTheLife());
Console.ReadKey();
}
}
}


(Code creates UnityContainer instance and the uses it to retrieve instance of user class which WhatIsTheMeaningOfTheLife method is then shown in console output.)


User class is implemented like this:

namespace ConsoleApplication1
{
public class User
{
private readonly ICompanyManager companyManager;

public User(ICompanyManager companyManager)
{
this.companyManager = companyManager;
}

public int WhatIsTheMeaningOfTheLife()
{
return 42;
}
}
}


(User class constructor accepts ICompanyManager parameter which BTW is totally not used in the method used in console application.)


Although totally irrelevant for this blog post, here’s ICompanyManger class code (just not to have any secrets :)):

namespace ConsoleApplication1
{
public interface ICompanyManager
{
void NotImportantMethod();
}
}

If I would run this code as it is I would be rewarded by the nice Unity ResolutionFailedException


Resolution of the dependency failed, type = "ConsoleApplication1.User", name = "". Exception message is: The current build operation (build key Build Key[ConsoleApplication1.User, null]) failed: The parameter companyManager could not be resolved when attempting to call constructor ConsoleApplication1.User(ConsoleApplication1.ICompanyManager companyManager). (Strategy type BuildPlanStrategy, index 3)


Reason is pretty obvious: Unity container didn’t have any mapping defined for ICompanyManager which is required in order for user class to be required.


AutoMockingUnityContainer


Is just a class looking like this

using System.Diagnostics;
using Microsoft.Practices.Unity;

namespace UnityAMC
{
public class AutoMockingUnityContainer : UnityContainer
{
private readonly MockingHelper mockingHelper;

public AutoMockingUnityContainer()
{
mockingHelper = new MockingHelper(this);
}

public override object Resolve(System.Type t, string name)
{
try
{
return base.Resolve(t, name);
}
catch (ResolutionFailedException)
{
Debug.WriteLine(string.Format("Conflict resolution of type:{0}", t));
return mockingHelper.ConstructInstance(t);
}

}
}
}


As you can see no magic there and it does exactly what everyone would expect:



  • Inherit the UnityContainer

  • Override the Resolve method

  • Adds to that override Try Catch block which in case of ResolutionFailedException exception calls the mockingHelper ConstructInstance method

  • Mocking helper instance is stored in a field and constructed with pointer to current unity container in AMCContainer constructor

MockingHelper class


Is just 90 line long class looking like this:

using System;
using System.Diagnostics;
using System.Reflection;
using Microsoft.Practices.Unity;
using Rhino.Mocks;

namespace UnityAMC
{
public class MockingHelper
{
private readonly IUnityContainer unityContainer;
readonly MockRepository mockRepository = new MockRepository();
private const string DebugCategory = "UnityAMC.MockingHelper";

public MockingHelper(IUnityContainer unityContainer)
{
this.unityContainer = unityContainer;
}

#region Helper methods
///


/// Construct the instance.
///

/// The type which is to be constructed.
/// An instance of service type.
public object ConstructInstance(Type serviceType)
{
ConstructorInfo constructorInfo;
try
{
constructorInfo = GetGreediestConstructor(serviceType.GetConstructors());
}
catch (Exception)
{
try
{
Debug.WriteLine(string.Format("Mock created - {0}", serviceType), DebugCategory);

// returning mock of service not added to container
return this.mockRepository.DynamicMock(serviceType, new object[0]);
}
catch (Exception ex2)
{
return new AutoMockingContainerContainerResolutionException(string.Format("Auto mocking failed for type:{0}", serviceType), ex2);
}
}

var constructorParameters = constructorInfo.GetParameters();
var arguments = new object[constructorParameters.Length];

var counter = 0;
foreach (var parameterInfo in constructorParameters)
{
arguments[counter++] = this.unityContainer.Resolve(parameterInfo.ParameterType, string.Empty);
}

return constructorInfo.Invoke(arguments);
}

///


/// Gets the greediest constructor.
///

/// The constructor infos.
/// Greediest constructor.
private static ConstructorInfo GetGreediestConstructor(ConstructorInfo[] constructorInfos)
{
if (constructorInfos.Length == 0)
{
throw new InvalidOperationException("No available constructors.");
}

if (constructorInfos.Length == 1)
{
return constructorInfos[0];
}

var result = constructorInfos[0];
for (int i = 1; i < constructorInfos.Length; i++)
{
if (constructorInfos[i].GetParameters().Length > result.GetParameters().Length)
{
result = constructorInfos[i];
}
}

return result;
}
#endregion
}
}


GetGreediestConstructor method purpose is to get from a given collection of type constructor info's the one which has the most arguments.


ConstructInstanceMethod does next things:



  • For a given type tries to get greediest constructor

    • If no constructor available on a given type  (ex. in case of interface) it returns dynamic mock.

  • code then iterates through the greediest constructor parameters and tries to resolve each one of them

  • if resolution of any of them fails the procedure goes again just this time ConstructInstanceMethod would go one level deeper in object graph.

And that’s about it…


If I would modify my console app code to use AutoMockingUnityContainer instead of UnityContainer, I would end with code looking like this

using System;
using Microsoft.Practices.Unity;
using UnityAMC;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
IUnityContainer container = new AutoMockingUnityContainer();
var user = container.Resolve<User>();
Console.WriteLine(user.WhatIsTheMeaningOfTheLife());
Console.ReadKey();
}
}
}


Which would run just fine…


image


Conclusion


Although I found this way of doing Unity AMC pretty naive and dumb, it works perfectly in my test fixtures for couple of months already with 20 minutes spent on making it. If anyone do this on ninja way, I would be more then happy to start using that but in the meantime … :)


My little code example can be downloaded from here


Technorati Ознаке: ,,,

Filed under: Uncategorized 1 Comment