Testing a Module's Presenter

Topics: Prism v2 - WPF 3.5
Mar 19, 2009 at 5:35 PM

Hi,

I am using Prism 2.0 with WPF for my application and I created an MVP triplet for a Module of which I need to test the Presenter. The problem is that Prism/Unity is injecting several dependencies which is great at runtime in the shell but I am having trouble mocking them at test time in my unit tests.

My question is: How can I use Unity/Prism to do the same job in my unit tests? I tried Rhino mocks but it fails with an error (apparently there is no easy solution to it).

The presenter goes like this:

public class LookupFormPresenter : ILookupFormPresenter, INotifyPropertyChanged
    {
        private readonly IEventAggregator _eventAggregator;
        private readonly IRegionManager _regionManager;
        private readonly IUnityContainer _container;

        public LookupFormPresenter(
            IEventAggregator eventAggregator,
            IRegionManager regionManager,
            IUnityContainer container)
        {
            _eventAggregator = eventAggregator;
            _regionManager = regionManager;
            _container = container;
        }
etc...

The test would go like this:

 [Test]
public void GetCustomerPresenterTest()
{
    //here be magic and puff I get a valid container... how do I do this?

    var events = Container.Resolve<IEventAggregator>();
    var regions = Container.Resolve< IRegionManager  >();

    var presenter = new LookupFormPresenter(events, regions, Container);

    events.GetEvent<CustomerLookupReadyEvent>().Subscribe(
        customers =>
                {
                    Assert.AreEqual(1, customers.Count, "Wrong number of customers returned");
                    Assert.AreEqual("the test client", customers[0].Surname, "Wrong customer");
                });

    presenter.Find();
}

Any help appreciated and cheers for Prism. I am loving it.

Bartol

Mar 19, 2009 at 6:33 PM

Hi Bartol,

To check your presenters’ functionality you should not use Unity in your test. The way in which you are going to test your presenters will be creating an instance of it manually, using the new keyword, and passing mock class instance as parameters. This mock classes have to implement the interfaces that the presenter’s constructor is waiting. For example: Your LookupFormPresenter is expecting three parameters that should implement the IEventAggregator, IRegionManager and IUnityContainer interfaces respectively. So, you should create 3 mock classes that implement these interfaces and help you to isolate the presenter’s behavior.

 

Also notice that it is not a good practice to pass the IUnityContainer as a parameter if it will be used to locate a service or create 1 instance of another class. In this case, you should inject the service or object directly instead of the container.

A scenario where passing the IUnityContainer would be valid, is if you will be using the container as a factory, to dynamically create several instances of a class.

 

I think a good reference for you could be the mock classes created on the UIComposition.Modules.Employee.Desktop.Tests test project, inside the ViewDiscovery Quickstart solution (Or in the ViewInjection Quickstart solution). You can open this solution executing the BAT file called Desktop & Silverlight - Open QS - View Discovery QuickStart.bat inside the folder where you extracted the Composite Application Library (CAL).  

There you will find mock classes that implement the IRegionManager interface (check the MockRegionManager class) and the IUnityContainer (MockUnityContainer class), using these as example you will be able to create a mock class for the IEventAggregator interface quickly.

 

After you have all the mock classes implementing the required interfaces by the presenter’s constructor. You will be able to test your presenter in an isolated way instancing each of the mock class and passing them to the presenter as parameter.

 

So the test would look something like this:

 

 [Test]

public void GetCustomerPresenterTest()

{

    //here be magic and puff I get a valid container... how do I do this?

    var events = new MockEventAggregator();

    var regions = new MockRegionManager();

    var container = new MockUnityContainer();

    var presenter = new LookupFormPresenter(events, regions, container);

    events.GetEvent<CustomerLookupReadyEvent>().Subscribe(

        customers =>

                {

                    Assert.AreEqual(1, customers.Count, "Wrong number of customers returned");

                    Assert.AreEqual("the test client", customers[0].Surname, "Wrong customer");

                });

 

    presenter.Find();

}

 

Also, the EventAggregator QuickStart has an example on how to mock the EventAggregator in your unit tests.

 

Please, let me know if this helps.

 

Ezequiel Sculli

http://blogs.southworks.net/esculli/

Mar 19, 2009 at 7:50 PM
Hi,

Many thanks for the very complete answer and I am going to follow the quickstarts you pointed out.

I am passing the container to this presenter because it creates and destroys the module that shows the results of the search. Would this be bad practice too? I am doing it this way because I don't want the grid with the results to be on screen before the user does the search and I want to show something else if the search returns no results. There is probably a better way but I haven't found out yet.

Again, thanks,
Bartol
Apr 2, 2009 at 12:48 PM
I am trying to test my ViewModels and some BusinessLogic I implemented for a composite application.
But I don't really get the way of doing it. Is there somewhere something like a tutorial? I looked into the tests from the quickstarts but it is very hard for me to understand what these test are doing without any comments...
Would be great if anybody has a link for me!

Thanks in advance!