Using Rhino Mocks To Unit Test Events on Interfaces

Rhino I am working on some code using the Model View Presenter pattern for an article I am writing. I am using an event based approach based on the work that Fowler did. For the sake of this discussion, here is an example of a simplified view interface.

public interface IView
{
    event EventHandler Load;
}

In the spirit of TDD I follow this up with the shell of my Presenter class

public class Presenter
{
    public Presenter(IView view)
    {
        throw new NotImplementedException("Not implemented.");
    }
}

And this is where I reached my first dilemma. What is the best way to write my first unit test to test that the presenter class attaches itself to the view’s events? Well I could write a stub class that implements the interface and add a method to the stub that will raise the event. In this example, that would be quite easy, but in the real world, the interface might have multiple properties or methods and why bother going through the trouble to implement them all just to test one event? This is where a mock testing framework such as Rhino Mocks comes into play.

[Test]
public void VerifyAttachesToViewEvents()
{
    MockRepository mocks = new MockRepository();
    IView viewMock = (IView)mocks.CreateMock(typeof(IView));
    viewMock.Load += null;
    LastCall.IgnoreArguments();
    mocks.ReplayAll();
    new Presenter(viewMock);
    mocks.VerifyAll();   
}

The second line of code creates a dynamic proxy that implements the IView interface. In the third line, I set an expectation that the Load event will be attached to. The line afterwards tells Rhino Mocks to ignore the arguments in the last call. In other words, the Rhino Mocks will expect the that the Load event will be attached, but don’t worry about which method delegate gets attached to the event. Without that line, the test would expect that null is attached to the load event, which we do not want.

Finally we call ReplayAll(). I kinda think this is a misnomer since what it really is doing, as far as I know, is telling the mock framework that we are done setting all our expectations and we are going to actually conduct the test now. Up until this method call, every method, property, or event set on the mock instance is telling the mock that we are going to call that particular member. If one of the expected members is not invoked, the test has failed.

So finally after setting all these expectations, I create an instance of Presenter which is the code being tested. I then ask the mock framework to verify that all our expectations were met. Of course this test fails, which is good, since I haven’t yet implemented the presenter. Implementing the presenter is pretty straightforward.

public class Presenter
{
    IView view;
    public Presenter(IView view)
    {
        this.view = view;
        this.view.Load += new EventHandler(view_Load);
    }

    void view_Load(object sender, EventArgs e)
    {
        throw new Exception("Not implemented.");
    }
}

Now my test passes. But wait! It gets better. Now suppose I want to write a new test to test that the presenter handles the Load event. How do I raise the Load event on my mock IView instance? Rhino Mocks provides a way. First I will add a boolean property to the Presenter class named EventLoaded and then write the following test. This will allow me to know whether or not the event was raised. This is a contrived example of course. In a real project, you probably have some other condition you could test to verify that an event was raised.

I then write my test.

[Test]
public void VerifyLoadEventHandled()
{
    MockRepository mocks = new MockRepository();
    IView viewMock = (IView)mocks.CreateMock(typeof(IView));
    viewMock.Load += null;
    IEventRaiser loadRaiser 
         = LastCall.IgnoreArguments().GetEventRaiser();
    mocks.ReplayAll();
    Presenter presenter = new Presenter(viewMock);
    loadRaiser.Raise(viewMock, EventArgs.Empty);
    mocks.VerifyAll();
    Assert.IsTrue(presenter.EventLoaded);
}

This test looks similar to the last test, but note the bolded line (fourth line). This line creates an event raiser for the Load event (ignoring arguments to the event of course). Now I can use that later to raise the event after I create the presenter. Running this test fails, as expected. We have to finish the implementation of the Presenter class as follows:

public class Presenter
{
    IView view;
    public Presenter(IView view)
    {
        this.view = view;
        this.view.Load += new EventHandler(view_Load);
    }

    public bool EventLoaded
    {
        get { return this.eventLoaded; }
        set { this.eventLoaded = value; }
    }

    bool eventLoaded;

    void view_Load(object sender, EventArgs e)
    {
        this.eventLoaded = true;
    }
}

Now when I run the test, it succeeds. Pretty dang nifty. Many thanks to Ayende for clearing up some confusion I had with the Rhino Mocks documentation surrounding events.

Technorati tags: ,

What others have said

Requesting Gravatar... Ashwin Jun 25, 2006 11:22 AM
# re: Using Rhino Mocks To Unit Test Events on Interfaces
I saw an old post from you where you mentioned about your Yahoo IM account being attacked by the Phishing technique that uses Geocities.
Could you please share how you regained control of your yahoo Account. I am a victim of this Phishing and have not been able to regain control..changed the password once but to no avail. Any help will be deeply appreciated..
Requesting Gravatar... Haacked Jun 25, 2006 12:29 PM
# re: Using Rhino Mocks To Unit Test Events on Interfaces
I contacted Yahoo Customer Care and they helped me out. http://add.yahoo.com/fast/help/us/security/cgi_feedback

Good luck!
Requesting Gravatar... Chris Hedgate Jul 05, 2006 6:35 PM
# re: Using Rhino Mocks To Unit Test Events on Interfaces
Nice writeup, wish I had this when we implemented the same kind of tests for verifying that our presenters attaches to the view's events. But the docs and Rhino Mocks mailing list provided enough for us to get it right (more or less exactly the way you describe here).

However, recently we have changed our code a bit. Instead of having our views raising events that the presenters react to, we just have our views call the "event handler" methods in the presenter directly. This simplified writing the tests (as well as the views of course) a lot, and since there is always a one-to-one relationship between a view and a presenter we saw no need to use events. If there where many presenters that should be notified then events are go, but we thought this change was correct here and simplified things.

Any comments on that? More or less every example of MVP (in .Net) that I have seen uses events, so maybe we are missing something.
Requesting Gravatar... Haacked Jul 06, 2006 12:18 AM
# re: Using Rhino Mocks To Unit Test Events on Interfaces
Chris, that's interesting since most examples I've seen don't use events. The reason I started examining the event approach is that it decouples the view and presenter just a bit more. For example, the view doesn't need to know which methods of the presenter to call, it just raises its events as it normally does.

Most examples I've seen take the approach that you take and I think it may well end up being more readable. I'm still experimenting with different approaches.
Requesting Gravatar... Chris Hedgate Jul 06, 2006 10:41 PM
# re: Using Rhino Mocks To Unit Test Events on Interfaces
I think it's because Fowler uses events in the C# example from the MVP page of eaaDev. It's true that it decouples the view from the presenter, but I am not sure it is worth it vs readability and ease of writing tests. We are experimenting as well so it is interesting to see where you end up.
Requesting Gravatar... Tyler Gannon Oct 02, 2006 2:59 PM
# re: Using Rhino Mocks To Unit Test Events on Interfaces
I haven't tried what Chris suggests, for doing away with the events in this model, but IMO the events deliver the power of the model.

The thing is, there really shouldn't be a one-to-one relationship between model and presenter, if you're writing unit tests. Finally, we started doing this in the first place because it's REALLY hard to unit test your view, so with each bit the view has to know about the model you take, IMO, one step backwards.

Thanks for the article Phil, always a sound read.
# Faking interfaces with events or delegates using Rhino Mocks - level 300
I think mock objects themselves are a 300-level topic. I wish it weren't so, but from the folks I talk
Requesting Gravatar... you've been HAACKED Dec 13, 2006 6:45 AM
# [Tip Jar] Unit Test Events With Anonymous Delegates
[Tip Jar] Unit Test Events With Anonymous Delegates
Requesting Gravatar... AntonioGanci Feb 02, 2007 9:57 PM
# Alcuni link per approfondire il pattern Model View Presenter
Requesting Gravatar... you've been HAACKED Mar 27, 2007 10:53 AM
# Rhino Mocks 3.0 Released
Rhino Mocks 3.0 Released
Requesting Gravatar... Community Blogs Mar 27, 2007 11:30 AM
# Rhino Mocks 3.0 Released!
Ayende just announced the release of Rhino Mocks 3.0 . The downloads are located here . If you aren’t
Requesting Gravatar... Judah Apr 19, 2007 1:00 AM
# re: Using Rhino Mocks To Unit Test Events on Interfaces
Hey thanks alot -- this really helped me pick up events. I was afraid I'd have to use reflection to get the event handler name...but this gets around that. Brilliant! Thanks a bunch.
Requesting Gravatar... Al Apr 24, 2007 10:28 AM
# re: Using Rhino Mocks To Unit Test Events on Interfaces
Hi Phil, thanks for the post. I also started using RM for mock tests. I hit a snag though. Running the test throws this "Error 1 TestCase 'AS.Com.Business.ProjectSpace.Tests.ProjectAddViewPresenterTests.AddNewProject'
failed: System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation.
----> System.NullReferenceException : Object reference not set to an instance of an object.

This is my view:
---------------------------
public interface IProjectAddView
{
Project Project { get; }

event EventHandler ProjectAdded;
}

This is my presenter:
-----------------------------
public class ProjectAddViewPresenter
{
private IProjectAddView _view;
public ProjectAddViewPresenter(IProjectAddView view)
{
if (null == view)
{
throw new PresenterException("IProjectView can not be null.");
}

_view = view;

SubscribeToViewEvents();
}


public void SubscribeToViewEvents()
{
_view.ProjectAdded += new EventHandler(OnProjectCreated);
}

void OnProjectCreated(object sender, EventArgs args)
{
ProjectManager.CreateProject(_view.Project);
}
}


This is my test:
-----------------------------
[Test]
public void AddNewProject()
{
MockRepository mocks = new MockRepository();

IProjectAddView viewMock = (IProjectAddView)mocks.CreateMock(typeof(IProjectAddView));
viewMock.ProjectAdded += null;

IEventRaiser raiser = LastCall.IgnoreArguments().GetEventRaiser();
mocks.ReplayAll();

ProjectAddViewPresenter presenter = new ProjectAddViewPresenter(viewMock);

raiser.Raise(viewMock, EventArgs.Empty);

mocks.VerifyAll();
}

Do you have any idea why is the exception? I am sorry for such long post but I can not resolve this. Thanks a bunch in advance.
Requesting Gravatar... Haacked Apr 24, 2007 3:00 PM
# re: Using Rhino Mocks To Unit Test Events on Interfaces
My guess is that the NullReferenceException you're seeing is due to this call:

ProjectManager.CreateProject(_view.Project);

But it's hard to say without a stack trace. _view.Project is going to be null unless you mock that property. Something like:

Setup.Call(viewMock.Prop).PropertyBehavior();

For more on this, check out the Rhino Mocks documentation wiki.
Requesting Gravatar... Oren Ellenbogen's Blog Apr 27, 2007 4:55 AM
# Using Rhino Mocks to Unit Test Events on Interfaces, take 2
Requesting Gravatar... Oren Ellenbogen's Blog Apr 27, 2007 5:02 AM
# Using Rhino Mocks to Unit Test Events on Interfaces, take 2
Requesting Gravatar... Chris May May 28, 2007 4:37 AM
# Rhino Mocks
Requesting Gravatar... Chris May May 29, 2007 12:54 AM
# Rhino Mocks
Requesting Gravatar... Chris May May 29, 2007 1:12 AM
# Rhino Mocks
Requesting Gravatar... Brian Donahue May 29, 2007 3:15 AM
# re: Using Rhino Mocks To Unit Test Events on Interfaces
Hey Phil.

I've been playing with this, and read yours and Boodhoo's articles. He does not show an example of the concrete view code, and I was wondering if there any way around the awkward event wiring code in the concrete view? It seems confusing and redundant to have to wire up a "dummy" event in the codebehind that then checks to see if the Handler has subscribers, and if so, evokes the Handler.
Requesting Gravatar... Haacked May 29, 2007 5:02 AM
# re: Using Rhino Mocks To Unit Test Events on Interfaces
@Brian - I agree. I'm actually working on an update which will include some lessons learned. :) I now advocate a middle ground which I will explain.
Requesting Gravatar... Chris May May 29, 2007 11:34 AM
# Rhino Mocks
Requesting Gravatar... Irfan Jun 12, 2007 11:16 AM
# re: Using Rhino Mocks To Unit Test Events on Interfaces
I downLoaded the rhino mock 3.1
the interface IEventRaiser is not there.
what coould be the problem.
do i need to use some other DLL for that interface?
Requesting Gravatar... Julian Birch Dec 03, 2007 12:13 AM
# re: Using Rhino Mocks To Unit Test Events on Interfaces
I could be wrong, but I imagine your problem is that you need:

using Rhino.Mocks.Interfaces;
Requesting Gravatar... Luke Jan 23, 2008 9:33 AM
# re: Using Rhino Mocks To Unit Test Events on Interfaces
@Brian - I think I'm running into the same problem here. Every single one of my tests that invokes the presenter has to do all the dummy event wiring. This means that if I down the road add a new event handler that will be wired in the presenter than I have to update all of my tests... really annoying. Anyone know a good work around on this?
Requesting Gravatar... Justin Feb 20, 2008 12:00 AM
# re: Using Rhino Mocks To Unit Test Events on Interfaces
Thanks again Phil,

This is just another one of my stops on the road to implementing MVP - Supervising Controller with Rhino Mocks to test them.

Saved me again :D
Requesting Gravatar... Chris Woodward May 21, 2008 8:52 PM
# re: Using Rhino Mocks To Unit Test Events on Interfaces
One alternative to Chris Hedgate having his Views call the presenter directly and so needing to know about it, is to have an intermediary class than listens to the View and calls the appropriate method on the Presenter.

This means your unit tests that test the presenter logic don't need to deal with events. Testing that the intermediary maps View events to the correct Presenter method calls would be easier to test.
Requesting Gravatar... David White Aug 02, 2008 6:23 PM
# re: Using Rhino Mocks To Unit Test Events on Interfaces
Ayende appears to have deprecated the RhinoMocks approach your example shows. Do you know of the equivalent commands to use in RhinoMocks 3.5?
Requesting Gravatar... Sanket Sep 24, 2008 7:26 PM
# re: Using Rhino Mocks To Unit Test Events on Interfaces
it was awesome, thanks; And thanks to Ayende

What do you have to say?

(will show your gravatar)
Please add 1 and 2 and type the answer here: