-
Notifications
You must be signed in to change notification settings - Fork 1
Integration ServiceBus Extension
The TestTrackingDiagrams.Extensions.ServiceBus package adds Azure Service Bus messaging operation tracking to your test diagrams. Instead of opaque AMQP traffic, your sequence diagrams show classified operations like Send → orders-queue or Receive ← notifications-topic.
Using a shared library or abstraction layer? If your code doesn't use the
ServiceBusClientSDK directly — e.g. it goes through MassTransit, NServiceBus, a shared messaging library, or a custom abstraction — see the MassTransit Extension or Tracking Custom Dependencies for alternative approaches includingMessageTrackerandTrackingProxy<T>.
The Azure Service Bus SDK (Azure.Messaging.ServiceBus) uses AMQP by default, which does not go through an HttpMessageHandler pipeline. This extension uses a wrapper/decorator pattern instead — TrackingServiceBusClient wraps the real ServiceBusClient and returns tracked senders (TrackingServiceBusSender) and receivers (TrackingServiceBusReceiver) that intercept every operation and log it to RequestResponseLogger.
Because it logs to the same RequestResponseLogger as the standard TestTrackingMessageHandler, Service Bus operations appear alongside your HTTP API calls in the same sequence diagram — showing the complete flow from test → API → Service Bus.
Messaging operations (Send, Receive, Schedule, Peek) are tagged with MetaType.Event for blue async-messaging rendering in PlantUML diagrams.
dotnet add package TestTrackingDiagrams.Extensions.ServiceBusThe extension supports three verbosity levels that control how much detail appears in the diagrams:
| Level | Label shown | URI shown | Message body |
|---|---|---|---|
| Raw | Enum name (Send, SendBatch) |
servicebus://{queue} |
Included |
| Detailed | Operation with arrows (Send → orders-queue, Receive ← orders-queue) |
servicebus://{queue} or servicebus://{topic}/{subscription}
|
Included |
| Summarised | Simple name (Send, Receive, Complete) |
servicebus://{queue}/ |
None |
The default is Detailed.
| Operation | Raw | Detailed | Summarised |
|---|---|---|---|
| Send a message | Send |
Send → orders-queue |
Send |
| Send a batch (5 messages) | SendBatch |
Send (×5) → orders-queue |
Send |
| Schedule a message | Schedule |
Schedule → orders-queue |
Schedule |
| Receive a message | Receive |
Receive ← orders-queue |
Receive |
| Receive a batch (10 messages) | ReceiveBatch |
Receive (×10) ← orders-queue |
Receive |
| Peek | Peek |
Peek ← orders-queue |
Peek |
| Complete | Complete |
Complete |
Complete |
| Abandon | Abandon |
Abandon |
Abandon |
| Dead-letter | DeadLetter |
DeadLetter |
DeadLetter |
| Defer | Defer |
Defer |
Defer |
| Renew lock | RenewMessageLock |
RenewLock |
RenewLock |
The classifier recognises these Service Bus operations:
| Operation | Method Name |
|---|---|
Send |
SendMessageAsync |
SendBatch |
SendMessagesAsync |
Schedule |
ScheduleMessageAsync, ScheduleMessagesAsync
|
CancelSchedule |
CancelScheduledMessageAsync, CancelScheduledMessagesAsync
|
Receive |
ReceiveMessageAsync |
ReceiveBatch |
ReceiveMessagesAsync |
Peek |
PeekMessageAsync, PeekMessagesAsync
|
Complete |
CompleteMessageAsync |
Abandon |
AbandonMessageAsync |
DeadLetter |
DeadLetterMessageAsync |
Defer |
DeferMessageAsync |
RenewMessageLock |
RenewMessageLockAsync |
RenewSessionLock |
RenewSessionLockAsync |
GetSessionState |
GetSessionStateAsync |
SetSessionState |
SetSessionStateAsync |
Create a TrackingServiceBusClient that wraps your existing ServiceBusClient:
var trackingOptions = new ServiceBusTrackingOptions
{
ServiceName = "ServiceBus",
CallingServiceName = "My API",
Verbosity = ServiceBusTrackingVerbosity.Detailed,
CurrentTestInfoFetcher = () =>
{
var test = TestContext.Current.Test;
return test is not null
? (test.TestDisplayName, test.UniqueID)
: ("Unknown", "unknown");
}
};
var realClient = new ServiceBusClient("your-connection-string");
var trackedClient = new TrackingServiceBusClient(realClient, trackingOptions);
// Use trackedClient instead of realClient
var sender = trackedClient.CreateSender("orders-queue");
await sender.SendMessageAsync(new ServiceBusMessage("hello"));
var receiver = trackedClient.CreateReceiver("orders-queue");
var message = await receiver.ReceiveMessageAsync();Use AddServiceBusTestTracking() to replace an existing ServiceBusClient registration:
// In your test WebApplicationFactory or DI setup:
services.AddServiceBusTestTracking(new ServiceBusTrackingOptions
{
ServiceName = "ServiceBus",
CallingServiceName = "OrdersApi",
Verbosity = ServiceBusTrackingVerbosity.Detailed,
CurrentTestInfoFetcher = () => (TestContext.Current.Test.TestDisplayName, TestContext.Current.Test.UniqueID)
});This finds the existing ServiceBusClient registration, wraps it with TrackingServiceBusClient, and registers the tracked version. Your code that resolves TrackingServiceBusClient from DI will get the tracked wrapper.
| Property | Type | Default | Description |
|---|---|---|---|
ServiceName |
string |
"ServiceBus" |
Display name in diagrams for the Service Bus |
CallingServiceName |
string |
"Caller" |
Calling service name in diagrams |
Verbosity |
ServiceBusTrackingVerbosity |
Detailed |
Verbosity level (Raw, Detailed, Summarised) |
CurrentTestInfoFetcher |
Func<(string Name, string Id)>? |
null |
Required: provides test context for log correlation |
CurrentStepTypeFetcher |
Func<string?>? |
null |
Optional — returns the current BDD step type (Given/When/Then) |
v2.23.0+ Dual-Resolution:
ServiceBusTrackeraccepts an optionalIHttpContextAccessor? httpContextAccessorconstructor parameter for resolving test identity from HTTP request headers when running inside the SUT's request pipeline. See HTTP Tracking Setup#Dual-Resolution Test Identity (v2.23.0+) for details. |SetupVerbosity|ServiceBusTrackingVerbosity?|null| Verbosity override for the Setup phase. See Phase-Aware Tracking | |ActionVerbosity|ServiceBusTrackingVerbosity?|null| Verbosity override for the Action phase. See Phase-Aware Tracking | |TrackDuringSetup|bool|true| Whenfalse, tracking is suppressed during Setup. See Phase-Aware Tracking | |TrackDuringAction|bool|true| Whenfalse, tracking is suppressed during Action. See Phase-Aware Tracking |
Because ServiceBusSender and ServiceBusReceiver are sealed classes in the Azure SDK, this extension uses wrapper classes rather than DelegatingHandler or DispatchProxy:
ServiceBusClient (real)
└── TrackingServiceBusClient (wrapper)
├── CreateSender() → TrackingServiceBusSender (wraps ServiceBusSender)
└── CreateReceiver() → TrackingServiceBusReceiver (wraps ServiceBusReceiver)
Each wrapper delegates all calls to the real instance and adds tracking before/after each operation. The Inner property on each wrapper provides escape-hatch access to the original SDK object.
TrackingServiceBusSender tracks:
-
SendMessageAsync— logs message body (at Raw/Detailed) -
SendMessagesAsync— logs count -
ScheduleMessageAsync— logs message body, response includes sequence number -
CancelScheduledMessageAsync— logs sequence number
Untracked (pass-through): CreateMessageBatchAsync, CloseAsync
TrackingServiceBusReceiver tracks:
-
ReceiveMessageAsync— logs received message body in response -
ReceiveMessagesAsync— logs count in response -
PeekMessageAsync— logs peeked message body in response CompleteMessageAsyncAbandonMessageAsync-
DeadLetterMessageAsync— logs dead-letter reason (at Raw/Detailed) DeferMessageAsyncRenewMessageLockAsync
Untracked (pass-through): CloseAsync
ServiceBusTracker implements ITrackingComponent and auto-registers with TrackingComponentRegistry on construction. If the tracker is registered but never processes any operations, a passive warning appears in the console output and (when DiagnosticMode=true) in the HTML diagnostic report. This never throws or fails tests — see Diagnostics and Debugging for details.
Getting Started
Common Tasks
Integration Guides
- Integration xUnit3
- Integration xUnit2
- Integration NUnit
- Integration MSTest
- Integration TUnit
- Integration BDDfy xUnit3
- Integration LightBDD xUnit2
- Integration LightBDD xUnit3
- Integration LightBDD TUnit
- Integration ReqNRoll xUnit2
- Integration ReqNRoll xUnit3
- Integration ReqNRoll TUnit
Extensions
- Integration AtlasDataApi Extension
- Integration BigQuery Extension
- Integration Bigtable Extension
- Integration BlobStorage Extension
- Integration ClickHouse Extension
- Integration CloudStorage Extension
- Integration CosmosDB Extension
- Integration Dapper Extension
- Integration DynamoDB Extension
- Integration EF Core Relational Extension
- Integration Elasticsearch Extension
- Integration EventBridge Extension
- Integration EventHubs Extension
- Integration Grpc Extension
- Integration Kafka Extension
- Integration MassTransit Extension
- Integration MongoDB Extension
- Integration MySqlConnector Extension
- Integration Npgsql Extension
- Integration Oracle Extension
- Integration PubSub Extension
- Integration Redis Extension
- Integration S3 Extension
- Integration ServiceBus Extension
- Integration SNS Extension
- Integration Spanner Extension
- Integration SqlClient Extension
- Integration Sqlite Extension
- Integration SQS Extension
- Integration StorageQueues Extension
- Integration OpenTelemetry Extension
- Integration DispatchProxy Extension
- Integration MediatR Extension
- Integration PlantUML IKVM
Configuration
- Tracking Dependencies
- Tracking Custom Dependencies
- HTTP Tracking Setup
- Report Configuration
- Diagram Customisation
- Phase-Aware Tracking
- Content Formatting
- PlantUML Server Configuration
Features
- Generated Reports
- Search Syntax
- Component Diagrams
- PlantUML Browser Rendering
- Inline SVG Rendering
- Internal Flow Tracking
- Tags and Attributes
- Excluding Requests
- Excluded Headers
- Multi-Host Test Architectures
- Event-Driven Architecture Testing
- Service Bus Tracking Patterns
- Background Thread Correlation
- Parallel-Safe Background Correlation
- Event & Message Tracking
- Assertion Tracking
- Step Tracking
- Tabular Attributes
- Large Response and Diagram Handling
- Diagnostics and Debugging
- CI Summary Integration
- CI Artifact Upload
- Merging Parallel Reports
Reference