# Unit Testing NServiceBus This sample shows how to write unit tests for various NServiceBus components with Arrange-Act-Assert (AAA) style tests. This sample is a test project that uses [NUnit](https://nunit.org/) and testable helper implementations from the `NServiceBus.Testing` package. ## Testing a handler Given the following handler: ```cs public class MyReplyingHandler : IHandleMessages { public Task Handle(MyRequest message, IMessageHandlerContext context) { return context.Reply(new MyResponse()); } } ``` The following test verifies that the handler received a `Reply`: ```cs [Test] public async Task ShouldReplyWithResponseMessage() { var handler = new MyReplyingHandler(); var context = new TestableMessageHandlerContext(); await handler.Handle(new MyRequest(), context); var repliedMessages = context.RepliedMessages; Assert.That(repliedMessages, Has.Length.EqualTo(1)); Assert.That(repliedMessages[0].Message, Is.InstanceOf()); } ``` ## Testing a saga > [!NOTE] > See [saga scenario testing](/nservicebus/testing/saga-scenario-testing.md) to see an alternate method of saga testing where an entire scenario consisting of multiple messages can be tested at once. Here's an example of a saga that processes an order and gives a 10% discount for orders above 1000: ```cs public class DiscountPolicy : Saga, IAmStartedByMessages { public Task Handle(SubmitOrder message, IMessageHandlerContext context) { Data.CustomerId = message.CustomerId; Data.TotalAmount += message.TotalAmount; if (Data.TotalAmount >= 1000) { return ProcessWithDiscount(message, context); } return ProcessOrder(message, context); } Task ProcessWithDiscount(SubmitOrder message, IMessageHandlerContext context) { var processOrder = new ProcessOrder { CustomerId = Data.CustomerId, OrderId = message.OrderId, TotalAmount = message.TotalAmount * (decimal)0.9 }; return context.Send(processOrder); } Task ProcessOrder(SubmitOrder message, IMessageHandlerContext context) { var processOrder = new ProcessOrder { CustomerId = Data.CustomerId, OrderId = message.OrderId, TotalAmount = message.TotalAmount }; return context.Send(processOrder); } protected override void ConfigureHowToFindSaga(SagaPropertyMapper mapper) { mapper.MapSaga(saga => saga.CustomerId) .ToMessage(msg => msg.CustomerId); } } ``` The following unit tests checks that the discount was applied to the total amount: ```cs [Test] public async Task ShouldProcessDiscountOrder() { var saga = new DiscountPolicy { Data = new DiscountPolicyData() }; var context = new TestableMessageHandlerContext(); var discountOrder = new SubmitOrder { CustomerId = Guid.NewGuid(), OrderId = Guid.NewGuid(), TotalAmount = 1000 }; await saga.Handle(discountOrder, context); var processMessage = (ProcessOrder)context.SentMessages[0].Message; Assert.That(processMessage.TotalAmount, Is.EqualTo(900)); } ``` ## Testing a behavior The following custom behavior adds a header to an outgoing message when the message is of the type `MyResponse`: ```cs public class CustomBehavior : Behavior { public override Task Invoke(IOutgoingLogicalMessageContext context, Func next) { if (context.Message.MessageType == typeof(MyResponse)) { context.Headers.Add("custom-header", "custom header value"); } return next(); } } ``` The behavior can be tested similar to a message handler or a saga by using a testable representation of the context: ```cs [Test] public async Task ShouldAddCustomHeaderToMyResponse() { var behavior = new CustomBehavior(); var context = new TestableOutgoingLogicalMessageContext { Message = new OutgoingLogicalMessage(typeof(MyResponse), new MyResponse()) }; await behavior.Invoke(context, () => Task.CompletedTask); Assert.That(context.Headers["custom-header"], Is.EqualTo("custom header value")); } ``` ## Testing IEndpointInstance usage `IEndpointInstance` is the main entry point for messaging APIs when used outside the pipeline (i.e. outside a saga or handler). One common example is sending a message from a webpage controller. For example the following controller has an injected `IEndpointInstance` and handles a request and sends a message. ```cs public class MyController { IEndpointInstance endpointInstance; public MyController(IEndpointInstance endpointInstance) { this.endpointInstance = endpointInstance; } public Task HandleRequest() { return endpointInstance.Send(new MyMessage()); } } ``` The test that verifies a `Send` happened: ```cs [Test] public async Task ShouldSendMessage() { var endpointInstance = new TestableEndpointInstance(); var handler = new MyController(endpointInstance); await handler.HandleRequest(); var sentMessages = endpointInstance.SentMessages; Assert.That(sentMessages, Has.Length.EqualTo(1)); Assert.That(sentMessages[0].Message, Is.InstanceOf()); } ```