Unittest NServiceBus saga

NServiceBus has it’s own unit test support framework. The nuget package is NServiceBus.Testing. Below I’ll demonstrate how to use it with an example saga from the book Learning NServiceBus.

VerifyUserEmailPolicy Saga

The saga is used to verify an e-mail address before a user is actually created. In the diagram below I’ve described what happens.

  1. User signs up with an email address
  2. Saga sends email to verify the address
  3. Saga waits for User verify command and could timeout (not in my code)
  4. User clicks links in email to verify the address
  5. Saga allows new user to be created

VerifyUserEmailPolicy

Unittests

To test this saga add a unittest project to your solution, add references to the saga and command projects, install the NServiceBus.Testing package.

Below the test methods for the saga. Since I use the tips from Art of unit testing this should be readable for you.

[TestMethod]
public void SagaStartsOnCreateNewUserCmdReceived() {
    var testSaga = CreateNewVerifyUserEmailPolicySaga();
    var message = CreateValidCreateNewUserCmd();
    testSaga.When(saga => saga.Handle(message))
            .AssertSagaCompletionIs(false);
}

[TestMethod]
public void SagaSendsSendVerifyEmailCmdOnCreateNewUserCmdReceived() {
    var testSaga = CreateNewVerifyUserEmailPolicySaga();
    var message = CreateValidCreateNewUserCmd();
    testSaga.ExpectSend<SendVerificationEmailCmd>()
            .When(saga => saga.Handle(message));
}

[TestMethod]
public void SagaCompletesOnUserVerifyEmailCmdReceived() {
    var message = CreateValidUserVerifyEmailCmd();
    var testSaga = CreateRunningVerifyUserEmailPolicySagaWaitingForMessage(message);
    testSaga.When(saga => saga.Handle(message))
            .AssertSagaCompletionIs(true);
}

[TestMethod]
public void SagaSendsCreateNewUserWithVerifiedEmailCmdOnUserVerifyEmailCmdReceived() {
    var message = CreateValidUserVerifyEmailCmd();
    var testSaga = CreateRunningVerifyUserEmailPolicySagaWaitingForMessage(message);
    testSaga.ExpectSend<CreateNewUserWithVerifiedEmailCmd>()
            .When(saga => saga.Handle(message));
}

The plumbing code for better maintenance is below.

public VerifyUserEmailPolicyTest() {
    // initialize NServiceBus.Testing
    Test.Initialize();
}

private Saga<VerifyUserEmailPolicy> CreateNewVerifyUserEmailPolicySaga() {
    return Test.Saga<VerifyUserEmailPolicy>();
}
private Saga<VerifyUserEmailPolicy> CreateRunningVerifyUserEmailPolicySagaWaitingForMessage
    (UserVerifyEmailCmd waitingForCommand) {
    var testSaga = CreateNewVerifyUserEmailPolicySaga();
    var message = CreateValidCreateNewUserCmd();
    testSaga.ExpectSend<SendVerificationEmailCmd>(reply => {
            waitingForCommand.VerificationCode = reply.VerificationCode;
            waitingForCommand.EmailAddress = reply.EmailAddress;
        }).When(saga => saga.Handle(message));
    return testSaga;
}
private CreateNewUserCmd CreateValidCreateNewUserCmd() {
    return new CreateNewUserCmd() {
        EmailAddress = "my.email@provider.com",
        Name = "Eric Tummers "
    };
}
private UserVerifyEmailCmd CreateValidUserVerifyEmailCmd() {
    return new UserVerifyEmailCmd()  {
        EmailAddress = "some.email@provider.com",
        VerificationCode = "ABCD"
    };
}

Execution of the unit tests takes longer for the first test because of the Test.Initialize (10ms). After that it performs rather good. (2ms each) Other frameworks like RhinoMocks have the same payoff.

Now we can verify the working of this NServiceBus saga. Be sure to test the endpoints for CreateNewUserWithVerifiedEmailCmd and SendVerificationEmailCmd.

References

About erictummers

Working in a DevOps team is the best thing that happened to me. I like challenges and sharing the solutions with others. On my blog I’ll mostly post about my work, but expect an occasional home project, productivity tip and tooling review.
This entry was posted in Test and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.