Yet another way of raising events from mocks

Update 2008-06-26: This is now in the Rhino Mocks trunk, so it should be available as part of the 3.5 release.

I’ve been playing around with raising events from mocks for the last couple of nights, and think I’ve finally come up with an approach that works for me. Finding a nice way of raising these events is particularly tricky for mock object frameworks, as the C# compiler is really picky about how you can use event references. For example, let’s look at a very useful interface:

public interface IDoSomething {    
    event EventHandler SomethingDone;
}

Outside of a class that implements IDoSomething, the only time we can reference SomethingDone is when we are adding or removing listeners (x.SomethingDone += someEventHandler; or x.SomethingDone -= someEventHandler;). (C#’s lack of real support for System.Void is partly to blame here, as both these operations are void.)

To raise an event on a mock object, it would be lovely to be able to code something like this:

var mock = mocks.DynamicMock();
mock.Raise(mock.SomethingDone, mock, EventArgs.Empty);

Unfortunately due to the aforementioned constraint, the emphasised part of the code will give a compiler error stating "The event ‘IDoSomething.SomethingDone’ can only appear on the left hand side of += or -=".

There are a few workarounds for this. Let’s start with the standard Rhino Mocks approach. (I’m using Rhino Mocks 3.5 beta and xUnit.net here – feel free to translate from [Fact] to [Test] if you use NUnit, MBUnit et al.)

[Fact]
public void Raise_event_old_style() {
    var mock = mocks.DynamicMock<IDoSomething>();
    mock.SomethingDone += null;
    IEventRaiser eventRaiser = LastCall.IgnoreArguments().GetEventRaiser();
    mocks.ReplayAll();

    var wasCalled = false;
    mock.SomethingDone += (sender, e) => wasCalled = true;
    eventRaiser.Raise(mock, EventArgs.Empty);

    mocks.VerifyAll();  
    Assert.True(wasCalled);
}

Rhino Mocks records the expectation that an event handler is added, then uses LastCall to ignore the argument and gets an IEventRaiser for the last event referenced. That IEventRaiser can be used later on to raise our event. Phil Haack has a helpful post which explains a bit more about this approach.

When I first saw this I must admit it seemed like a lot of noise that obscured what I was really trying to do. This got worse when I started playing around with the new Arrange - Act - Assert syntax and I didn’t want to go through the whole replay / verify cycle. So I started looking at the Rhino Mocks implementation of IEventRaiser, the EventRaiser class. This class lets us do this:

[Fact]
public void Raise_event_using_string_for_event_name() {
    var mock = mocks.DynamicMock<IDoSomething>();
    var wasCalled = false;
    mock.SomethingDone += (sender, e) => wasCalled = true;

    var eventRaiser = EventRaiser.Create(mock, "SomethingDone");
    eventRaiser.Raise(mock, EventArgs.Empty);
    
    Assert.True(wasCalled);
}

Here we can specify the relevant event using a string. This works nicely and is easy to read, but causes problems when refactoring and means we don’t get intellisense or compiler assistance. Ayende has written about this approach, comparing it with the LastCall.GetEventRaiser() approach we used last time.

I wasn’t overjoyed about either of these, and while searching around for other options I found another of Ayende’s posts (I think his blog is about 30% of the web… great stuff :)), asking for feedback on a more natural syntax for raising events from mocks. This looked a bit like this:

mock.MyEvent += EventRaiser.Raise(this, EventArgs.Empty);

I quite liked this, but there were a few complaints in the comments about subscribing to and raising the event at the same time. The post was from about 12 months prior to me writing this and, as I’m using a recent Rhino Mocks build and couldn’t find it, it looks like nothing came of this. Let’s look for a compromise that also fits in nicely with our Arrange - Act - Assert approach. First we’ll see what we can get working based on the first, LastCall.GetEventRaiser() approach used:

[Fact]
public void Raise_event_with_new_arrange_act_assert_syntax() {
    //Arrange
    var mock = MockRepository.GenerateMock<IDoSomething>();
    var wasCalled = false;
    mock.SomethingDone += (sender, e) => wasCalled = true;
    
    var eventRaiser = 
        mock
        .Stub(x => x.SomethingDone += null)
        .IgnoreArguments()
        .GetEventRaiser();
    
    //Act
    eventRaiser.Raise(mock, EventArgs.Empty);

    //Assert
    Assert.True(wasCalled);
}

Here we are specifying a fairly useless stub so we can get an IEventRaiser. We are still using ye olde x.SomethingDone += null trick (albeit with a lambda to neaten it up), but we are pretty much stuck with that if we want strong typing on this as discussed at the beginning of this post.

I think this looks a bit more cohesive now we are using the lambda. We have one statement that is fairly obviously getting an IEventRaiser, rather than a null event handler floating around on its own confusing poor people like me :). Beyond aesthetics, this cohesion can let us pull out this functionality and start getting closer to a neater syntax. For now we’ll just whack this in a .NET 3.5 extension method, but we could probably find a better home for it (it can go in a standalone class but the final syntax doesn’t read quite as well to me).

public static class EventRaiserExtensions {
    private static IEventRaiser GetEventRaiserFromSubscription<TEventSource>(
        this TEventSource mock, Action<TEventSource> eventSubscription) {
        return mock
            .Stub(eventSubscription)
            .IgnoreArguments()
            .GetEventRaiser();
    }
    
    public static void Raise<TEventSource>(this TEventSource mock, Action<TEventSource> eventSubscription, object sender, EventArgs args) {
        var eventRaiser = GetEventRaiserFromSubscription(mock, eventSubscription);
        eventRaiser.Raise(sender, args);
    }

    public static void Raise<TEventSource>(this TEventSource mock, Action<TEventSource> eventSubscription, params object[] args) {
        var eventRaiser = GetEventRaiserFromSubscription(mock, eventSubscription);
        eventRaiser.Raise(args);
    }        

    public static void Raise<TEventSource>(this TEventSource mock, Action<TEventSource> eventSubscription) {
        var eventRaiser = GetEventRaiserFromSubscription(mock, eventSubscription);
        eventRaiser.Raise(mock, EventArgs.Empty);
    }    
}

The emphasised bit of code is the stub call we did last time, but this time pulled out into one method. The main bits are the Raise<TEventSource> extension methods, which combine all the steps and give us an easy syntax for calling an event on a mock based on an event subscription delegate. So our example now looks like this:

[Fact]
public void Suggestion_for_raising_events() {
    var mock = MockRepository.GenerateMock<IDoSomething>();
    var wasCalled = false;
    mock.SomethingDone += (sender, e) => wasCalled = true;

    mock.Raise(x => x.SomethingDone += null, mock, EventArgs.Empty);

    Assert.True(wasCalled);
}

The implementation itself might need work, but I reckon that syntax is pretty neat considering the limitations of C#. Of course, you’re welcome to think otherwise, so please leave a comment expressing your outrage and/or contempt :).

Disclaimer: I am fairly new to Rhino Mocks (have tended to stick to manual test doubles) and especially to Arrange - Act - Assert (it’s only in beta at present), so this might fail pretty hard in other circumstances. Still, I thought I’d post the syntax in case it gave more knowledgable people some good ideas :)

Comments