Archive for the ‘Unit Testing’ category

Testing Message Handlers with NServiceBus

September 27th, 2009

One of the great things that ships with is a dll called “NServiceBus.Testing” which provides us with the ability to easily test your sagas. This enables us to move forward with greater confidence in knowing that the code that we have written will function as expected when we move the code into integration testing and then production.  Most of what i talk about here is in direct reference the 1.9 release of NServiceBus. If you have not seen how Saga’s are unit tested in NServiceBus have a read of Udi’s post on the forum. This post however is about how to test a Plain old Message Handler.

Let us being with looking at a sample handler.

   1: public class FileProcessMessageHandler:IMessageHandler<ProcessFileMessage>

   2: {

   3:     public IBus Bus { get; set; }

   4:     public IFileProcessor FileProcessor {get;set;}

   5:     public void Handle(ProcessFileMessage message)

   6:     {

   7:         if (FileProcessor.Run(message.FileIdentfier,message.FileSystemLocation))

   8:         {

   9:             var msg = Bus.CreateInstance<FileProcessedMessage>(m => {

  10:                                  m.FileIdentifier = message.FileIdentfier; });

  11:             Bus.Publish(msg);

  12:         }

  13:         else

  14:         {

  15:             Bus.Publish<UnknownFileTypeMessage>(m => { 

  16:                                 m.FileIdentifer = message.FileIdentfier; });

  17:         }

  18:     }

  19: }

This code in and of itself is highly testable. We have two interfaces that are injected into the class, excellent candidates for a mock. However when i first started down this path my first inclination was to use a manual mock, before moving on to trying to use Moq, however after spending time the fluent saga testing API in NServiceBus I realized that it was what was needed in this situation a MockBus.

MockBus is essentially the same as what is in the NServiceBus.Testing library. However because that version is geared towards testing sagas, it required changing the way the Saga class was created, and to allow for creating a version that would work with message handler. The new structure looks like the class diagram below.

 

NServiceBus Testing Class Diagram

 

What Changed

  1. The Saga class has become the MockBus class and no longer has the static method called Test() which created the Saga instance.
  2. The MockBusForSaga has the method CreateInstance<T> which replaces the Test() method in the old Saga class.
  3. Introduced a MockBusForMessageHandler which has a CreateInstance<T,TK>() method that creates the message handler.

Having this structure now enables us to write our tests for our message handlers very simply in a fashion that does not require to understand Rhino Mocks, though having a understanding of the errors you get from the mock bus is important as all the messages that are bubbled out are Rhino Mock Messages.

   1: [Test]

   2: public void when_file_processor_succeds_message_handler_will_publish_a_file_processed_message()

   3: {

   4:     FileProcessMessageHandler msgHandler;

   5:     var mock_bus = MockBusForMessageHandler.CreateInstance

   6:                             <FileProcessMessageHandler,ProcessFileMessage>(out msgHandler);

   7:     var fileID = Guid.NewGuid();

   8:     msgHandler.FileProcessor = SetupAndReturnFileProcessor(true);

   9:     mock_bus.ExpectPublish<FileProcessedMessage>(d => d.FileIdentifier == fileID)

  10:         .When(() => msgHandler.Handle(CreateProcessFileRequest(fileID)));

  11: }

 

Lets have a look  when make a call to CreateInstance<FileProcessMessageHandler,ProcessFileMessage>(out msgHandler)

   1: public static MockBusForMessageHandler CreateInstance<T, TK>(out T handler)

   2: where TK : IMessage

   3: where T : IMessageHandler<TK>, new()

   4: {

   5:     handler = (T) Activator.CreateInstance(typeof (T));

   6:     var mocks = new MockRepository();

   7:     var bus = mocks.DynamicMock<IBus>();

   8:     try

   9:     {

  10:         typeof (T).GetProperty(“Bus”, BindingFlags.Instance | BindingFlags.Public)

  11:             .SetValue(handler, bus, null);

  12:     }

  13:     catch

  14:     {/**swallow if they dont have a Bus defined in the class**/}

  15:     List<Type> typesToMap;

  16:     MessageMapper mapper = GetMapperAndInitialize(out typesToMap);

  17:     return new MockBusForMessageHandler(mocks, bus, mapper, typesToMap);

  18: }

The beauty in this code is all hidden away in the MockBus (aka NServiceBus.Testing.Saga) thank you Udi for this,

The bus is instantiated when the object is created however no expectations are recorded until the When() method is called in the test just before the delegate is run. Once the delegate is run you will get the callbacks to the ExpectPublish where you can assert that not only did you get the correct type of message but the contents as well.

The code for this is available on the or go to it NServiceBus.Extensions.Testing download here