Skip to content

Integration StorageQueues Extension

Aryeh Citron edited this page Apr 24, 2026 · 10 revisions

The TestTrackingDiagrams.Extensions.StorageQueues package adds Azure Storage Queue operation tracking to your test diagrams. Instead of showing raw HTTP requests like POST /my-queue/messages, your sequence diagrams show classified operations like Send → my-queue or Receive ← my-queue.

Using a shared library or abstraction layer? If your code doesn't use the Storage Queues SDK directly — e.g. it goes through MassTransit, a shared messaging library, or a custom abstraction — see the MassTransit Extension or Tracking Custom Dependencies for alternative approaches including MessageTracker and TrackingProxy<T>.


How It Works

The Azure Storage Queues SDK translates all operations into HTTP requests to the Azure Storage REST API. StorageQueueTrackingMessageHandler is a DelegatingHandler that intercepts these HTTP requests, classifies each one into a Queue operation (SendMessage, ReceiveMessages, PeekMessages, DeleteMessage, etc.) using the HTTP method, URL path, and query parameters, then logs it to RequestResponseLogger with a human-readable label.

Because it logs to the same RequestResponseLogger as the standard TestTrackingMessageHandler, Storage Queue operations appear alongside your HTTP API calls in the same sequence diagram — showing the complete flow from test → API → Storage Queue.


Install

dotnet add package TestTrackingDiagrams.Extensions.StorageQueues

Verbosity Levels

The extension supports three verbosity levels that control how much detail appears in the diagrams:

Level Method shown URI shown Headers Request body Response body
Raw HTTP method (POST, GET, etc.) Full URI with query parameters All except excluded set Full content Full content
Detailed Classified label (Send → my-queue) Clean URI (storagequeue:///my-queue) Filtered (noisy Storage headers excluded) Full content Full content
Summarised Operation name (SendMessage) Clean URI (storagequeue:///my-queue) None None None

The default is Detailed.

Diagram Label Examples

Operation Raw Detailed Summarised
Send message POST: .../my-queue/messages Send → my-queue SendMessage
Receive messages GET: .../my-queue/messages Receive ← my-queue ReceiveMessages
Peek messages GET: .../my-queue/messages?peekonly=true Peek ← my-queue PeekMessages
Delete message DELETE: .../my-queue/messages/msg-id Delete DeleteMessage
Update message PUT: .../my-queue/messages/msg-id Update UpdateMessage
Clear messages DELETE: .../my-queue/messages Clear → my-queue ClearMessages
Create queue PUT: .../my-queue CreateQueue CreateQueue
Delete queue DELETE: .../my-queue DeleteQueue DeleteQueue
Get properties GET: .../my-queue?comp=metadata GetProperties GetProperties
Set metadata PUT: .../my-queue?comp=metadata SetMetadata SetMetadata
List queues GET: /?comp=list ListQueues ListQueues

Classified Operations

The classifier recognises these Storage Queue operations from the SDK's HTTP traffic:

Operation HTTP Pattern
SendMessage POST /{queue}/messages
ReceiveMessages GET /{queue}/messages
PeekMessages GET /{queue}/messages?peekonly=true
DeleteMessage DELETE /{queue}/messages/{messageId}
UpdateMessage PUT /{queue}/messages/{messageId}
ClearMessages DELETE /{queue}/messages
CreateQueue PUT /{queue}
DeleteQueue DELETE /{queue}
GetProperties GET /{queue}?comp=metadata
SetMetadata PUT /{queue}?comp=metadata
ListQueues GET /?comp=list
Other Unrecognised requests

In Summarised mode, Other operations are silently skipped.


Setup

Option A: With QueueClientOptions Extension (Recommended)

var trackingOptions = new StorageQueueTrackingMessageHandlerOptions
{
    ServiceName = "StorageQueue",
    CallingServiceName = "My API",
    Verbosity = StorageQueueTrackingVerbosity.Detailed,
    CurrentTestInfoFetcher = () =>
    {
        var test = TestContext.Current.Test;
        return test is not null
            ? (test.TestDisplayName, test.UniqueID)
            : ("Unknown", "unknown");
    }
};

var clientOptions = new QueueClientOptions();
clientOptions.WithTestTracking(trackingOptions);

var client = new QueueServiceClient(connectionString, clientOptions);

WithTestTracking sets the Transport property on QueueClientOptions to route all HTTP requests through the tracking handler.

Option B: Manual HttpClient Construction

If you need more control over the HTTP pipeline:

var trackingOptions = new StorageQueueTrackingMessageHandlerOptions
{
    ServiceName = "StorageQueue",
    CallingServiceName = "My API",
    Verbosity = StorageQueueTrackingVerbosity.Detailed,
    CurrentTestInfoFetcher = () =>
    {
        var test = TestContext.Current.Test;
        return test is not null
            ? (test.TestDisplayName, test.UniqueID)
            : ("Unknown", "unknown");
    }
};

var trackingHandler = new StorageQueueTrackingMessageHandler(trackingOptions);
var httpClient = new HttpClient(trackingHandler);
var transport = new Azure.Core.Pipeline.HttpClientTransport(httpClient);

var clientOptions = new QueueClientOptions
{
    Transport = transport
};

var client = new QueueServiceClient(connectionString, clientOptions);

Option C: In DI-based Tests (WebApplicationFactory)

builder.ConfigureTestServices(services =>
{
    services.AddSingleton(sp =>
    {
        var trackingOptions = new StorageQueueTrackingMessageHandlerOptions
        {
            ServiceName = "StorageQueue",
            CallingServiceName = "My API",
            Verbosity = StorageQueueTrackingVerbosity.Detailed,
            CurrentTestInfoFetcher = () =>
            {
                var test = TestContext.Current.Test;
                return test is not null
                    ? (test.TestDisplayName, test.UniqueID)
                    : ("Unknown", "unknown");
            }
        };

        var clientOptions = new QueueClientOptions();
        clientOptions.WithTestTracking(trackingOptions);

        return new QueueServiceClient("UseDevelopmentStorage=true", clientOptions);
    });
});

Configuration Reference

StorageQueueTrackingMessageHandlerOptions

Property Type Default Description
ServiceName string "StorageQueue" The participant name shown in the diagram for the Storage Queue service
CallingServiceName string "Caller" The participant name shown for the service making Queue calls
Verbosity StorageQueueTrackingVerbosity Detailed Controls how much detail appears in the diagram (Raw, Detailed, Summarised)
CurrentTestInfoFetcher Func<(string Name, string Id)>? null Returns the current test's name and ID. Required — if null, requests are forwarded but not logged
CurrentStepTypeFetcher Func<string?>? null Optional — returns the current BDD step type (Given/When/Then)
ExcludedHeaders HashSet<string> See below Headers to exclude from diagrams in Raw/Detailed mode
SetupVerbosity StorageQueueTrackingVerbosity? null Verbosity override for the Setup phase. See Phase-Aware Tracking
ActionVerbosity StorageQueueTrackingVerbosity? null Verbosity override for the Action phase. See Phase-Aware Tracking
TrackDuringSetup bool true When false, tracking is suppressed during Setup. See Phase-Aware Tracking
TrackDuringAction bool true When false, tracking is suppressed during Action. See Phase-Aware Tracking

Default Excluded Headers

The following Azure Storage headers are excluded by default (they add noise without diagnostic value):

  • Authorization
  • x-ms-date
  • x-ms-version
  • x-ms-client-request-id
  • x-ms-return-client-request-id
  • User-Agent
  • Cache-Control

Override ExcludedHeaders to customise:

new StorageQueueTrackingMessageHandlerOptions
{
    ExcludedHeaders = ["Authorization", "x-ms-date"] // Only exclude these two
}

CurrentTestInfoFetcher by Framework

The CurrentTestInfoFetcher delegate must return the current test's name and unique ID. How you obtain this depends on your test framework:

xUnit v3:

CurrentTestInfoFetcher = () =>
{
    var test = TestContext.Current.Test;
    return test is not null
        ? (test.TestDisplayName, test.UniqueID)
        : ("Unknown", "unknown");
}

xUnit v2 (with TestTrackingDiagrams.xUnit2):

using TestTrackingDiagrams.xUnit2;

CurrentTestInfoFetcher = () => XUnit2TestTrackingContext.GetCurrentTestInfo()

NUnit:

CurrentTestInfoFetcher = () =>
{
    var test = TestContext.CurrentContext.Test;
    return (test.FullName, test.ID);
}

Extension Methods

QueueClientOptions.WithTestTracking()

public static QueueClientOptions WithTestTracking(
    this QueueClientOptions options,
    StorageQueueTrackingMessageHandlerOptions trackingOptions,
    HttpMessageHandler? innerHandler = null)

Configures QueueClientOptions to use StorageQueueTrackingMessageHandler. Sets options.Transport to an HttpClientTransport backed by an HttpClient wrapping the tracking handler. The optional innerHandler parameter sets the inner handler (defaults to HttpClientHandler).


Invocation Validation

StorageQueueTrackingMessageHandler implements ITrackingComponent and auto-registers with TrackingComponentRegistry on construction. At report generation time, unused components are automatically detected and surfaced as console warnings and in the diagnostic report (when DiagnosticMode=true). This never throws or fails tests.

See Diagnostics and Debugging for full details on the TrackingComponentRegistry API.

Home


Demo


Getting Started

Common Tasks

Integration Guides

Extensions

Configuration

Features

Reference

Clone this wiki locally