After my last post, I had quite a healthy discussion with Alex Hung (@alexhung) on you guessed it, testability and mocking. Alex’s observation was although my extension methods were easy to use, they were difficult to test. He had gone and implemented a similar user experience but through using a custom wrapper which added Publish and Subscribe methods but called to EA under the covers. His wrapper implements an interface that is easy to mock.

The question then was how can you mock the new extension methods? Before getting into the how lets first answer the question of why?

Here are unit tests that should illustrate what I want to do.

[TestFixture]
public class When_SelectOrder_is_invoked {
  [Test]
  public void then_controller_publishes_OrderSelected() 
  {
    //mock out the event aggregator;  
    var mock = new Mock<IEventAggregator>() 
    var controller = new OrderController(mock.Object);
    var order=new Order();
    controller.SelectOrder(order);
    mock.Verify(ea=>ea.Publish(order));
  }
}
[TestFixture]
public class When_OrderViewModel_is_created {
  [Test]
  public void then_subscribes_to_OrderSelected() {
    //mock out the event aggregator;  
    var mock = new Mock<IEventAggregator>() 
    var vm = new OrderViewModel(mock.Object);
    mock.Verify(ea=>ea.Subscribe(vm.OnOrderSelected));
  }
}

Looks simple enough right? I am creating a mock EventAggregator, passing it in and then verifying that the Publish and Subscribe methods are called. Both Alex and I originally though that would work. Winking smile Though Alex was a bit skeptical.

However the reality is that it cannot work. The reason is because I am creating a mock of IEventAggregator but the methods I want to mock are not on the event aggregator itself, they are extension methods! Yet another proof that what looks like it will work in the blackboard of your mind, often doesn’t hold up any water in the real world.

There is hope though. Extension methods CAN be mocked, but it takes a bit of refactoring. Daniel Cazzulino (@kzu) has a great post on this here. The approach I came up with is based on his. For my extension methods here are the steps I went through in that refactoring.

  1. Created an IEventAggregatorExtensionsProvider interface. This interface has all the methods from my EventAggregatorExtensions class however, the methods are all non-static (obviously) and I removed this from the first param. Other than that the signatures are the same.
  2. Created EventAggregatorExtensionsProvider which implements IEventAggregatorExtensionsProvider. I ripped the implementation of each method out of EventAggregatorExtenions and then moved it into this provider.
  3. Added a private static variable _Provider of type IEventAggregatorExtensionsProvider to EventAggregatorExtensions. The variable initializes itself to a new instance of EventAggregatorExtensionsProvider.
  4. Changed all public methods in EventAggregatorExtensions to delegate directly to the _provider instance.
  5. Added a static SetProvider method which accepts an IEventAggregatorExtensionsProvider which it then overrides _provider with.

Here’s what the resulting code now looks like (which has grown a bit from my first Codepaste): http://codepaste.net/woqq1d

With these changes I can now pass in a mock of IEventAggregatorExtensionsProvider to do exactly what I want. Now my unit tests read like this:

[TestFixture]
public class When_SelectOrder_is_invoked {
  [Test]
  public void then_controller_publishes_OrderSelected()
  {
    //mock out the provider
    var mock = new Mock<IEventAggregatorExtensionsProvider>();
    var ea = new EventAggregator();
    EventAggregatorExtensions.SetProvider(mock.Object);
    var controller = new OrderController(ea);
    var order = new Order();
    controller.SelectOrder(order);
    mock.Verify(p=>p.Publish(ea, order));
}
[TestFixture]
public class When_OrderViewModel_is_created {
  [Test]
  public void then_subscribes_to_OrderSelected()
  {
    //mock out the provider
    var mock = new Mock<IEventAggregatorExtensionsProvider>();
    var ea = new EventAggregator();
    EventAggregatorExtensions.SetProvider(mock.Object);
    var vm = new OrderViewModel(ea);
    mock.Verify(p=>p.Subscribe(ea, vm.OnOrderSelected));
    
  }
}

The main difference is that I am now creating a mock of the extensions provider rather than the event aggregator itself. That means that my mock is the thing that will get invoked by the classes under test.

Actually the EA instance I create in the unit tests is just a dummy and could even be null as extensions methods can be invoked on null instances. That’s because my classes under test are only accessing the extension methods. However I passed it in because it is entirely conceivable one might want to access the actual instance methods.

To be fair there is more ceremony here than the approach that Alex was suggesting as you have to mock the provider and pass in an event aggregator. However the difference I think is marginal, and it works nicely and is completely testable.

What do you think?