NServiceBus Home

Contents

  • Long-Running Processes
  •     Sagas

Unit testing with NServiceBus

Automated testing would be better

Developing enterprise-scale distributed systems is hard
and testing them is just as challenging a task.

The architectural approach supported by NServiceBus
makes these challenges more manageable. And the
testing facilities provided actually make
unit testing endpoints and workflows easy.

Developers can now develop their service layers
and long-running processes using test-driven development.

Unit testing the service layer

The service layer in an NServiceBus application is made out of message handlers. Each class typically handles one specific type of message. Testing these classes is most often focused on their externally visible behavior - the types of messages they send or reply with. This is as simple to test as could be expected:

[Test]
public void TestHandler()
{
    Test.Initialize();

    Test.Handler<YourMessageHandler>()
        .ExpectReply<YourResponseMessage>(m => m.String == "hello")
        .OnMessage<YourRequestMessage>(m => m.String = "hello");
}

What this test is saying that when a message of the type YourRequestMessage is processed by YourMessageHandler, it will respond with a message of the type YourResponseMessage. Also, if the request message's String property value is "hello" than that will also be the value of the String property of the response message.

Testing header manipulation

One of the responsibilities of the message handlers in the service layer is using data from headers found in the request to make decisions, as well as setting headers on top of the response messages. This is how this kind of functionality can be tested:

[Test]
public void TestHandler()
{
    Test.Initialize();

    Test.Handler<YourMessageHandler>()
        .SetIncomingHeader("Test", "abc")
        .ExpectReply<YourResponseMessage>(m => m.String == "hello")
        .AssertOutgoingHeader("Test", "abc")
        .OnMessage<YourRequestMessage>(m => m.String = "hello");
}

This test sets the value of the incoming header key "Test" to be the value "abc". The test also asserts that the value of the outgoing header key "Test" will be "abc" as well.

Injecting additional dependencies into the service layer

Many of the message handling classes in the service layer will make use of other objects to perform their work. When testing these classes, you'll want to replace those objects with "stubs" so that the class under test is isolated. Here's how that's done:

[Test]
public void TestHandler()
{
    Test.Initialize();
    // initialize your mock-object library

    var yourObj = // mock out the relevant interface

    Test.Handler<YourMessageHandler>()
        .WithExternalDependencies(h => h.Dependency = yourObj)
        // rest of your test
}

One dependency that many message handlers will have is on the bus. That dependency will be filled automatically by the testing infrastructure and does not need to be mocked out in your test.

Other service layer testing functionality

For every method on the bus there is a corresponding test method that sets up an expectation for that call as shown below:

Test handler methods

Legal

“NServiceBus” is among the trademarks of NServiceBus Ltd. All other product and company names and marks mentioned are the property of their respective owners and are mentioned for identification purposes only.

© 2010 NServiceBus Ltd. All rights reserved.