Rig.TUnit.Messaging.ServiceBus
0.1.0-beta.2
dotnet add package Rig.TUnit.Messaging.ServiceBus --version 0.1.0-beta.2
NuGet\Install-Package Rig.TUnit.Messaging.ServiceBus -Version 0.1.0-beta.2
<PackageReference Include="Rig.TUnit.Messaging.ServiceBus" Version="0.1.0-beta.2" />
<PackageVersion Include="Rig.TUnit.Messaging.ServiceBus" Version="0.1.0-beta.2" />
<PackageReference Include="Rig.TUnit.Messaging.ServiceBus" />
paket add Rig.TUnit.Messaging.ServiceBus --version 0.1.0-beta.2
#r "nuget: Rig.TUnit.Messaging.ServiceBus, 0.1.0-beta.2"
#:package Rig.TUnit.Messaging.ServiceBus@0.1.0-beta.2
#addin nuget:?package=Rig.TUnit.Messaging.ServiceBus&version=0.1.0-beta.2&prerelease
#tool nuget:?package=Rig.TUnit.Messaging.ServiceBus&version=0.1.0-beta.2&prerelease
Rig.TUnit.Messaging.ServiceBus
Microsoft-official Azure ServiceBus emulator fixture (
servicebus-emulator+ SQL Edge sidecar) with native session FIFO listener and runtime topology administration.
What this package is
The Rig.TUnit Azure ServiceBus provider. ServiceBusFixture orchestrates
Microsoft's official ServiceBus emulator
(mcr.microsoft.com/azure-messaging/servicebus-emulator) plus the
required SQL Edge sidecar (per C-001 — emulator uses SQL for internal
state). EULA acceptance is mandatory: options.AcceptEula must be set
to true explicitly. Ships:
ServiceBusEventSender— sender withSendContextoverload mappingSessionKey→SessionId,PartitionKey→PartitionKey(with equality validation),DeduplicationKey→MessageId.ServiceBusListener— non-session subscription processor.ServiceBusSessionListener— session-aware processor on top ofServiceBusClient.CreateSessionProcessor; populatesCapturedMessage.SessionKeyfrom the broker'sSessionIdand surfaces broker errors viaObservedErrors/LastError.ServiceBusAdministrationHelper— wrapsServiceBusAdministrationClient(≥ 7.20.1) with idempotent create-or-update operations for topics, subscriptions (withRequiresSession,MaxDeliveryCount,LockDuration), SQL rule filters, and queues.ServiceBusTopologyBuilder+ provider-scoped interfaces (IServiceBusTopologyBuilder,IServiceBusTopicConfig,IServiceBusSubscriptionConfig,IServiceBusQueueConfig) wired to the rig viaServiceBusRigBuilder.WithTopology(…).ServiceBusDeadLetterProbe— DLQ inspection helper for tests that assert poison-message routing.
When to use it
- Integration tests for Azure Service Bus topics, subscriptions, and queues.
- Asserting session-ordered delivery (
OrderingAssert.PerKeyMonotonicwithSessionKey). - Declaring topology at runtime from test code — no
service-bus-config.jsonseed required (per Feature 007 T016). - Verifying SQL rule filter routing (e.g.
Region='EU'). - Verifying dead-letter + retry behaviour at
MaxDeliveryCount. - Not for: unit tests; mock
ServiceBusSender/ServiceBusReceiver.
Prerequisites
- .NET 10 SDK
- Docker Desktop / Colima (emulator + SQL Edge ~1.8 GB combined)
- EULA acceptance (
AcceptEula = true) Azure.Messaging.ServiceBus(transitive)
Quick start
using Azure.Messaging.ServiceBus;
using Azure.Messaging.ServiceBus.Administration;
using Rig.TUnit.Messaging.Helpers;
using Rig.TUnit.Messaging.ServiceBus.Fixtures;
using Rig.TUnit.Messaging.ServiceBus.Helpers;
using Rig.TUnit.Messaging.ServiceBus.Topology;
// 1) Spin the emulator + SQL sidecar.
await using var fx = new ServiceBusFixture(o => o.AcceptEula = true);
await fx.InitializeAsync();
// 2) Provision topology at runtime via the admin client (no JSON seed).
var admin = new ServiceBusAdministrationClient(fx.ConnectionString);
var helper = new ServiceBusAdministrationHelper(admin);
await helper.CreateSubscriptionIfNotExistsAsync(
"orders", "shipping", requiresSession: true, ct);
// 3) Send + receive with native session FIFO.
await using var client = new ServiceBusClient(fx.ConnectionString);
await using var sender = new ServiceBusEventSender(client, "orders");
await using var listener = new ServiceBusSessionListener(client, "orders", "shipping");
await listener.StartAsync(ct);
await sender.SendAsync(
"{\"orderId\":1}",
context: new SendContext(SessionKey: "customer-42"),
ct: ct);
Equivalent with the WithTopology rig hook:
services.AddRigTUnit(rig =>
rig.UseServiceBus(RigConnect.FromValue(cs), sb =>
sb.WithTopology(t =>
t.Topic("orders")
.Subscription("orders", "shipping", s => s.WithRequiresSession())
.Subscription("orders", "billing"))));
Options
| Property | Type | Default | Description |
|---|---|---|---|
EmulatorImage |
string |
"mcr.microsoft.com/azure-messaging/servicebus-emulator:latest" |
Emulator image |
SqlEdgeImage |
string |
"mcr.microsoft.com/azure-sql-edge:latest" |
SQL sidecar |
StartupTimeoutSeconds |
int |
300 |
Both containers boot |
AcceptEula |
bool |
false |
MUST be true explicitly |
SqlSaPassword |
string |
"RigTUnit_P@ss1" |
SQL Edge SA |
Fixture + helper APIs
Rig.TUnit.Messaging.ServiceBus.Fixtures.ServiceBusFixtureRig.TUnit.Messaging.ServiceBus.Options.ServiceBusFixtureOptionsRig.TUnit.Messaging.ServiceBus.Builder.ServiceBusRigBuilder— shipsWithTopology(Action<IServiceBusTopologyBuilder>).Rig.TUnit.Messaging.ServiceBus.Helpers.ServiceBusListenerRig.TUnit.Messaging.ServiceBus.Helpers.ServiceBusSessionListener— exposesObservedSessions,ObservedErrors,LastError.Rig.TUnit.Messaging.ServiceBus.Helpers.ServiceBusEventSender— shipsSendAsync(string, SendContext, …)overload.Rig.TUnit.Messaging.ServiceBus.Topology.IServiceBusTopologyBuilderRig.TUnit.Messaging.ServiceBus.Topology.IServiceBusTopicConfig·IServiceBusSubscriptionConfig·IServiceBusQueueConfigRig.TUnit.Messaging.ServiceBus.Topology.ServiceBusTopologyBuilderRig.TUnit.Messaging.ServiceBus.Topology.ServiceBusAdministrationHelperRig.TUnit.Messaging.ServiceBus.Helpers.ServiceBusDeadLetterProbe
Per-test isolation
Per-test topic + subscription named with {IsolationKey}. Emulator
config file is regenerated per fixture to declare the per-test topology;
teardown tears down both containers (the emulator's in-SQL state dies
with the SQL container).
Parallelism + performance
- First-run pull: ~120 s (~1.8 GB combined).
- Warm startup: ~45 s (emulator + SQL init).
- Per-op send: ~5–10 ms.
- Parallelism: 2–4 concurrent tests; the SQL sidecar is the bottleneck.
Troubleshooting
Failed to accept EULA— setAcceptEula = true. The failure is deliberate and loud so no-one silently accepts commercial terms.Topic not found— emulator config regeneration raced with topology assertion; fixture waits for topic existence via the admin client before returning.
See docs/troubleshooting.md#servicebus.
Provider quirks + edge cases
- Service Bus sessions preserve FIFO within a session; cross-session
ordering is best-effort. Tests must declare session IDs explicitly via
SendContext.SessionKeyand assert withOrderingAssert.PerKeyMonotonic(listener, m => m.SessionKey, …). SendContext.SessionKeyandSendContext.PartitionKeymust be equal if both are supplied on a session-aware entity —ServiceBusEventSenderthrowsInvalidOperationExceptionbefore the broker round-trip.SendContext.DeduplicationKeyrequiresRequiresDuplicateDetectionon the entity; the topology builder exposesIServiceBusQueueConfig.WithDuplicateDetection(TimeSpan)/IServiceBusSubscriptionConfig.WithDuplicateDetection(TimeSpan).- Topology is applied idempotently (
CreateOrUpdate*), so re-running the sameWithTopologydeclaration in a parallel test is safe. - Emulator capability gaps (probed by
ServiceBusEmulatorCapabilityProbeTests) are documented indocs/providers/service-bus.md. Tests that need un-emulated features (advanced SQL filter types, auto-forwarding, dead-letter TTL semantics, partitioned-entity reconfiguration, premium-tier > 256 KB messages) must run against real Azure and use[Skip]on the emulator path per C-004.
Benchmarks
See ServiceBusMessagingBenchmarks.cs;
baseline in benchmarks/baseline-005.json.
Related docs
- Architecture diagram
- Glossary
- Provider deep-dive:
docs/providers/service-bus.md(session FIFO,WithTopology, emulator capability table, JSON-seed migration). - Family base:
Rig.TUnit.Messaging - Feature design: Sessions & Partitions · Topology Builder
License
MIT. See LICENSE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Azure.Messaging.ServiceBus (>= 7.20.1)
- Bogus (>= 35.6.1)
- Microsoft.Extensions.Configuration (>= 10.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 10.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.0)
- Microsoft.Extensions.Options (>= 10.0.0)
- Microsoft.Extensions.Options.DataAnnotations (>= 10.0.0)
- Rig.TUnit.Messaging (>= 0.1.0-beta.2)
- Testcontainers (>= 4.11.0)
- Testcontainers.MsSql (>= 4.11.0)
- Testcontainers.ServiceBus (>= 4.11.0)
- TUnit.Core (>= 1.34.5)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Rig.TUnit.Messaging.ServiceBus:
| Package | Downloads |
|---|---|
|
Rig.TUnit.All
Meta-package containing every Rig.TUnit.* package. DISCOURAGED — prefer per-feature or per-stack meta-packages (Rig.TUnit, Rig.TUnit.Microservices). |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.0-beta.2 | 47 | 4/27/2026 |
| 0.0.0-alpha.0.14 | 44 | 4/26/2026 |