From ff70f39d4262fb94a6b6f4d63801592cf4467e90 Mon Sep 17 00:00:00 2001 From: Daniel Marbach Date: Sun, 24 May 2026 17:18:49 +0200 Subject: [PATCH 1/5] Use built-in test independence features --- ...nfigureEndpointAzureServiceBusTransport.cs | 4 +--- .../TestIndependenceHeaderBehavior.cs | 15 ------------ .../TestIndependenceSkipBehavior.cs | 23 ------------------- 3 files changed, 1 insertion(+), 41 deletions(-) delete mode 100644 src/NServiceBus.Envelope.CloudEvents.ASB.AcceptanceTests/TestIndependenceHeaderBehavior.cs delete mode 100644 src/NServiceBus.Envelope.CloudEvents.ASB.AcceptanceTests/TestIndependenceSkipBehavior.cs diff --git a/src/NServiceBus.Envelope.CloudEvents.ASB.AcceptanceTests/ConfigureEndpointAzureServiceBusTransport.cs b/src/NServiceBus.Envelope.CloudEvents.ASB.AcceptanceTests/ConfigureEndpointAzureServiceBusTransport.cs index 3f4e1a1..dcb4fff 100644 --- a/src/NServiceBus.Envelope.CloudEvents.ASB.AcceptanceTests/ConfigureEndpointAzureServiceBusTransport.cs +++ b/src/NServiceBus.Envelope.CloudEvents.ASB.AcceptanceTests/ConfigureEndpointAzureServiceBusTransport.cs @@ -32,9 +32,7 @@ public Task Configure(string endpointName, EndpointConfiguration configuration, recoverability.Immediate(config => config.NumberOfRetries(0)); recoverability.Delayed(config => config.NumberOfRetries(0)); - configuration.Pipeline.Register("TestIndependenceHeaderBehavior", typeof(TestIndependenceHeaderBehavior), "Appends the TestRunId to outgoing messages"); - configuration.Pipeline.Register("TestIndependenceSkipBehavior", typeof(TestIndependenceSkipBehavior), "Skips messages not created during the current test."); - + configuration.EnableTestIndependence(); configuration.EnforcePublisherMetadataRegistration(endpointName, publisherMetadata); return Task.CompletedTask; diff --git a/src/NServiceBus.Envelope.CloudEvents.ASB.AcceptanceTests/TestIndependenceHeaderBehavior.cs b/src/NServiceBus.Envelope.CloudEvents.ASB.AcceptanceTests/TestIndependenceHeaderBehavior.cs deleted file mode 100644 index f749b88..0000000 --- a/src/NServiceBus.Envelope.CloudEvents.ASB.AcceptanceTests/TestIndependenceHeaderBehavior.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace NServiceBus.Envelope.CloudEvents.ASB.AcceptanceTests; - -using AcceptanceTesting; -using Microsoft.Extensions.DependencyInjection; -using Pipeline; - -class TestIndependenceHeaderBehavior : IBehavior -{ - public Task Invoke(IOutgoingPhysicalMessageContext context, Func next) - { - var scenarioContext = context.Builder.GetRequiredService(); - context.Headers["$AcceptanceTesting.TestRunId"] = scenarioContext.TestRunId.ToString(); - return next(context); - } -} \ No newline at end of file diff --git a/src/NServiceBus.Envelope.CloudEvents.ASB.AcceptanceTests/TestIndependenceSkipBehavior.cs b/src/NServiceBus.Envelope.CloudEvents.ASB.AcceptanceTests/TestIndependenceSkipBehavior.cs deleted file mode 100644 index 0d2bccd..0000000 --- a/src/NServiceBus.Envelope.CloudEvents.ASB.AcceptanceTests/TestIndependenceSkipBehavior.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace NServiceBus.Envelope.CloudEvents.ASB.AcceptanceTests; - -using AcceptanceTesting; -using Microsoft.Extensions.DependencyInjection; -using NUnit.Framework; -using Pipeline; - -class TestIndependenceSkipBehavior : IBehavior -{ - public Task Invoke(ITransportReceiveContext context, Func next) - { - var scenarioContext = context.Builder.GetRequiredService(); - var testRunId = scenarioContext.TestRunId.ToString(); - - if (context.Message.Headers.TryGetValue("$AcceptanceTesting.TestRunId", out var runId) && runId != testRunId) - { - TestContext.Out.WriteLine($"Skipping message {context.Message.MessageId} from previous test run"); - return Task.CompletedTask; - } - - return next(context); - } -} \ No newline at end of file From 42fa6ccda3c31a879bcbdea979dc67cad76b16f3 Mon Sep 17 00:00:00 2001 From: Daniel Marbach Date: Sun, 24 May 2026 17:28:38 +0200 Subject: [PATCH 2/5] Disable configurawait --- .../.editorconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/NServiceBus.Envelope.CloudEvents.AcceptanceTests/.editorconfig b/src/NServiceBus.Envelope.CloudEvents.AcceptanceTests/.editorconfig index 67173de..1b4feb8 100644 --- a/src/NServiceBus.Envelope.CloudEvents.AcceptanceTests/.editorconfig +++ b/src/NServiceBus.Envelope.CloudEvents.AcceptanceTests/.editorconfig @@ -1,4 +1,5 @@ [*.cs] # Justification: Test project +dotnet_diagnostic.CA2007.severity = suggestion dotnet_diagnostic.PS0018.severity = suggestion \ No newline at end of file From aa223ab4b6f9bed040e5c2c2e7260817f10e3755 Mon Sep 17 00:00:00 2001 From: Daniel Marbach Date: Sun, 24 May 2026 17:28:51 +0200 Subject: [PATCH 3/5] Remove unneeded duplication --- ...ceptanceTestingTransportWithCloudEvents.cs | 62 +------------------ 1 file changed, 3 insertions(+), 59 deletions(-) diff --git a/src/NServiceBus.Envelope.CloudEvents.AcceptanceTests/ConfigureEndpointAcceptanceTestingTransportWithCloudEvents.cs b/src/NServiceBus.Envelope.CloudEvents.AcceptanceTests/ConfigureEndpointAcceptanceTestingTransportWithCloudEvents.cs index 42da7e7..045f433 100644 --- a/src/NServiceBus.Envelope.CloudEvents.AcceptanceTests/ConfigureEndpointAcceptanceTestingTransportWithCloudEvents.cs +++ b/src/NServiceBus.Envelope.CloudEvents.AcceptanceTests/ConfigureEndpointAcceptanceTestingTransportWithCloudEvents.cs @@ -1,8 +1,6 @@ namespace NServiceBus.AcceptanceTests; -using AcceptanceTesting.Customization; using AcceptanceTesting.Support; -using NUnit.Framework; public class ConfigureEndpointAcceptanceTestingTransportWithCloudEvents( bool useNativePubSub, @@ -11,68 +9,14 @@ public class ConfigureEndpointAcceptanceTestingTransportWithCloudEvents( bool? enforcePublisherMetadata = null) : IConfigureEndpointTestExecution { - public Task Cleanup() - { - try - { - if (Directory.Exists(storageDir)) - { - Directory.Delete(storageDir, true); - } - } - catch - { - // ignored - } + readonly ConfigureEndpointAcceptanceTestingTransport transport = new(useNativePubSub, useNativeDelayedDelivery, transactionMode, enforcePublisherMetadata); - return Task.CompletedTask; - } + public Task Cleanup() => transport.Cleanup(); public Task Configure(string endpointName, EndpointConfiguration configuration, RunSettings settings, PublisherMetadata publisherMetadata) { - var testRunId = TestContext.CurrentContext.Test.ID; - - string tempDir = - //can't use bin dir since that will be too long on the build agents - Environment.OSVersion.Platform == PlatformID.Win32NT ? @"c:\temp" : Path.GetTempPath(); - - storageDir = Path.Combine(tempDir, "acc", testRunId); - - var acceptanceTestingTransport = new AcceptanceTestingTransport( - enableNativeDelayedDelivery: useNativeDelayedDelivery, - enableNativePublishSubscribe: useNativePubSub) - { - StorageLocation = storageDir, - }; - - if (transactionMode.HasValue) - { - acceptanceTestingTransport.TransportTransactionMode = transactionMode.Value; - } - - if (enforcePublisherMetadata.GetValueOrDefault(false)) - { - configuration.EnforcePublisherMetadataRegistration(endpointName, publisherMetadata); - } - configuration.EnableCloudEvents(); - var routing = configuration.UseTransport(acceptanceTestingTransport); - - if (!useNativePubSub) - { - //apply publisher registrations required for message driven pub/sub - foreach (var publisherMetadataPublisher in publisherMetadata.Publishers) - { - foreach (var @event in publisherMetadataPublisher.Events) - { - routing.RegisterPublisher(@event, publisherMetadataPublisher.PublisherName); - } - } - } - - return Task.CompletedTask; + return transport.Configure(endpointName, configuration, settings, publisherMetadata); } - - string storageDir; } \ No newline at end of file From cd09fc458f234adf1f6a16baa083f944e38d34f6 Mon Sep 17 00:00:00 2001 From: Daniel Marbach Date: Sun, 24 May 2026 17:29:02 +0200 Subject: [PATCH 4/5] Cleanup test suite constraints --- .../TestSuiteConstraints.cs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/NServiceBus.Envelope.CloudEvents.AcceptanceTests/TestSuiteConstraints.cs b/src/NServiceBus.Envelope.CloudEvents.AcceptanceTests/TestSuiteConstraints.cs index 3a1d2c5..f0910c8 100644 --- a/src/NServiceBus.Envelope.CloudEvents.AcceptanceTests/TestSuiteConstraints.cs +++ b/src/NServiceBus.Envelope.CloudEvents.AcceptanceTests/TestSuiteConstraints.cs @@ -16,13 +16,7 @@ public partial class TestSuiteConstraints public bool SupportsPurgeOnStartup => false; - public IConfigureEndpointTestExecution CreateTransportConfiguration() - { - return new ConfigureEndpointAcceptanceTestingTransportWithCloudEvents(true, true); - } - - public IConfigureEndpointTestExecution CreatePersistenceConfiguration() - { - return new ConfigureEndpointAcceptanceTestingPersistence(); - } + public IConfigureEndpointTestExecution CreateTransportConfiguration() => new ConfigureEndpointAcceptanceTestingTransportWithCloudEvents(true, true); + + public IConfigureEndpointTestExecution CreatePersistenceConfiguration() => new ConfigureEndpointAcceptanceTestingPersistence(); } \ No newline at end of file From 84ef7de25e227f104c9218450c54fbde86dc2d3c Mon Sep 17 00:00:00 2001 From: Daniel Marbach Date: Sun, 24 May 2026 17:29:49 +0200 Subject: [PATCH 5/5] Simplify tests --- .../When_amqp_binary_message_received.cs | 21 +++++++----------- .../When_http_binary_message_received.cs | 22 +++++++------------ .../When_json_structured_message_received.cs | 21 +++++++----------- 3 files changed, 24 insertions(+), 40 deletions(-) diff --git a/src/NServiceBus.Envelope.CloudEvents.AcceptanceTests/CloudEvents/When_amqp_binary_message_received.cs b/src/NServiceBus.Envelope.CloudEvents.AcceptanceTests/CloudEvents/When_amqp_binary_message_received.cs index b364e56..2903591 100644 --- a/src/NServiceBus.Envelope.CloudEvents.AcceptanceTests/CloudEvents/When_amqp_binary_message_received.cs +++ b/src/NServiceBus.Envelope.CloudEvents.AcceptanceTests/CloudEvents/When_amqp_binary_message_received.cs @@ -1,9 +1,7 @@ namespace NServiceBus.AcceptanceTests.CloudEvents; using AcceptanceTesting; -using Configuration.AdvancedExtensibility; using EndpointTemplates; -using Envelope.CloudEvents; using NServiceBus.Pipeline; using NUnit.Framework; using Transport; @@ -34,8 +32,7 @@ public async Task An_amqp_binary_cloud_event_is_received() Sequencer = "000000000000000000000000000099240000000000c41c18" }); })) - .Done(c => c.MessageReceived) - .Run().ConfigureAwait(false); + .Run(); using (Assert.EnterMultipleScope()) { @@ -66,17 +63,15 @@ public Task Invoke(IDispatchContext context, Func next) } } - class Context : ScenarioContext + public class Context : ScenarioContext { - public bool MessageReceived { get; set; } public string MessageId { get; set; } public Dictionary Headers { get; set; } } - class Endpoint : EndpointConfigurationBuilder + public class Endpoint : EndpointConfigurationBuilder { - public Endpoint() - { + public Endpoint() => EndpointSetup(c => { var config = c.GetCloudEventsConfiguration(); @@ -85,15 +80,15 @@ public Endpoint() c.Pipeline.Register("CustomSerializationBehavior", new CustomSerializationBehavior(), "Serializing message"); }); - } - class Handler(Context testContext) : IHandleMessages + [Handler] + public class Handler(Context testContext) : IHandleMessages { public Task Handle(Message message, IMessageHandlerContext context) { testContext.MessageId = context.MessageId; testContext.Headers = context.MessageHeaders.ToDictionary(x => x.Key, x => x.Value); - testContext.MessageReceived = true; + testContext.MarkAsCompleted(); return Task.CompletedTask; } @@ -113,4 +108,4 @@ public class Message : IMessage public string Url { get; set; } public string Sequencer { get; set; } } -} +} \ No newline at end of file diff --git a/src/NServiceBus.Envelope.CloudEvents.AcceptanceTests/CloudEvents/When_http_binary_message_received.cs b/src/NServiceBus.Envelope.CloudEvents.AcceptanceTests/CloudEvents/When_http_binary_message_received.cs index 65aa685..570d9a7 100644 --- a/src/NServiceBus.Envelope.CloudEvents.AcceptanceTests/CloudEvents/When_http_binary_message_received.cs +++ b/src/NServiceBus.Envelope.CloudEvents.AcceptanceTests/CloudEvents/When_http_binary_message_received.cs @@ -1,9 +1,7 @@ namespace NServiceBus.AcceptanceTests.CloudEvents; using AcceptanceTesting; -using Configuration.AdvancedExtensibility; using EndpointTemplates; -using Envelope.CloudEvents; using NServiceBus.Pipeline; using NUnit.Framework; using Transport; @@ -34,8 +32,7 @@ public async Task An_http_binary_cloud_event_is_received() Sequencer = "000000000000000000000000000099240000000000c41c18" }); })) - .Done(c => c.MessageReceived) - .Run().ConfigureAwait(false); + .Run(); using (Assert.EnterMultipleScope()) { @@ -66,17 +63,15 @@ public Task Invoke(IDispatchContext context, Func next) } } - class Context : ScenarioContext + public class Context : ScenarioContext { - public bool MessageReceived { get; set; } public string MessageId { get; set; } public Dictionary Headers { get; set; } } - class Endpoint : EndpointConfigurationBuilder + public class Endpoint : EndpointConfigurationBuilder { - public Endpoint() - { + public Endpoint() => EndpointSetup(c => { var config = c.GetCloudEventsConfiguration(); @@ -85,22 +80,21 @@ public Endpoint() c.Pipeline.Register("CustomSerializationBehavior", new CustomSerializationBehavior(), "Serializing message"); }); - } - class Handler(Context testContext) : IHandleMessages + [Handler] + public class Handler(Context testContext) : IHandleMessages { public Task Handle(Message message, IMessageHandlerContext context) { testContext.MessageId = context.MessageId; testContext.Headers = context.MessageHeaders.ToDictionary(x => x.Key, x => x.Value); - testContext.MessageReceived = true; + testContext.MarkAsCompleted(); return Task.CompletedTask; } } } - public class Message : IMessage { public string Api { get; set; } @@ -113,4 +107,4 @@ public class Message : IMessage public string Url { get; set; } public string Sequencer { get; set; } } -} +} \ No newline at end of file diff --git a/src/NServiceBus.Envelope.CloudEvents.AcceptanceTests/CloudEvents/When_json_structured_message_received.cs b/src/NServiceBus.Envelope.CloudEvents.AcceptanceTests/CloudEvents/When_json_structured_message_received.cs index 7699c08..675ff3b 100644 --- a/src/NServiceBus.Envelope.CloudEvents.AcceptanceTests/CloudEvents/When_json_structured_message_received.cs +++ b/src/NServiceBus.Envelope.CloudEvents.AcceptanceTests/CloudEvents/When_json_structured_message_received.cs @@ -1,9 +1,7 @@ namespace NServiceBus.AcceptanceTests.CloudEvents; using AcceptanceTesting; -using Configuration.AdvancedExtensibility; using EndpointTemplates; -using Envelope.CloudEvents; using NServiceBus.Pipeline; using NUnit.Framework; using Transport; @@ -42,8 +40,7 @@ public async Task A_json_structured_cloud_event_is_received() } }); })) - .Done(c => c.MessageReceived) - .Run().ConfigureAwait(false); + .Run(); using (Assert.EnterMultipleScope()) { @@ -68,17 +65,15 @@ public Task Invoke(IDispatchContext context, Func next) } } - class Context : ScenarioContext + public class Context : ScenarioContext { - public bool MessageReceived { get; set; } public string MessageId { get; set; } public Dictionary Headers { get; set; } } - class Endpoint : EndpointConfigurationBuilder + public class Endpoint : EndpointConfigurationBuilder { - public Endpoint() - { + public Endpoint() => EndpointSetup(c => { var config = c.GetCloudEventsConfiguration(); @@ -87,15 +82,15 @@ public Endpoint() c.Pipeline.Register("CustomSerializationBehavior", new CustomSerializationBehavior(), "Serializing message"); }); - } - class Handler(Context testContext) : IHandleMessages + [Handler] + public class Handler(Context testContext) : IHandleMessages { public Task Handle(Message message, IMessageHandlerContext context) { testContext.MessageId = context.MessageId; testContext.Headers = context.MessageHeaders.ToDictionary(x => x.Key, x => x.Value); - testContext.MessageReceived = true; + testContext.MarkAsCompleted(); return Task.CompletedTask; } @@ -125,4 +120,4 @@ public class Message : IMessage public string Subject { get; set; } public NestedData Data { get; set; } } -} +} \ No newline at end of file