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.
- User signs up with an email address
- Saga sends email to verify the address
- Saga waits for User verify command and could timeout (not in my code)
- User clicks links in email to verify the address
- Saga allows new user to be created
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.