From 9a59e29de8ec4855d3cca89e2d498f1032cc1188 Mon Sep 17 00:00:00 2001 From: Christopher Read <1907605+christopherread@users.noreply.github.com> Date: Sat, 24 Oct 2026 23:37:21 -0700 Subject: [PATCH] Fix NetMQ tests failing when run together The pub/sub tests shared port 5556 between themselves and overlapped the 5555-5558 range TestServiceBusWithNetMq binds, which xUnit runs in parallel, and no test disposed its publishers, sources or buses. Give each pub/sub test its own port and dispose everything before asserting. Fixes #72 Co-Authored-By: Claude Opus 5.5 --- Obvs.NetMQ.Tests/TestPublishSubscribe.cs | 32 +++++++++++++-------- Obvs.NetMQ.Tests/TestServiceBusWithNetMq.cs | 5 ++++ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/Obvs.NetMQ.Tests/TestPublishSubscribe.cs b/Obvs.NetMQ.Tests/TestPublishSubscribe.cs index 1c2a9e99..ed4167dc 100644 --- a/Obvs.NetMQ.Tests/TestPublishSubscribe.cs +++ b/Obvs.NetMQ.Tests/TestPublishSubscribe.cs @@ -13,6 +13,8 @@ namespace Obvs.NetMQ.Tests { + // Each test uses its own port, clear of the ranges TestServiceBusWithNetMq binds, + // because xUnit runs test classes in parallel public class TestPublishSubscribe { [Fact, Trait("Category", "Explicit")] @@ -29,7 +31,7 @@ public async Task TestSendingAndReceivingStringsOverLocalHost() }, err => Console.WriteLine("Error: " + err)); - IMessageSource source = new MessageSource("tcp://localhost:5556", + IMessageSource source = new MessageSource("tcp://localhost:5560", new IMessageDeserializer[] { new JsonMessageDeserializer(), @@ -39,7 +41,7 @@ public async Task TestSendingAndReceivingStringsOverLocalHost() var sub = source.Messages.Subscribe(observer); - IMessagePublisher publisher = new MessagePublisher("tcp://localhost:5556", + IMessagePublisher publisher = new MessagePublisher("tcp://localhost:5560", new JsonMessageSerializer(), topic); await publisher.PublishAsync(new TestMessage1 { Id = 1 }); @@ -50,6 +52,10 @@ public async Task TestSendingAndReceivingStringsOverLocalHost() await publisher.PublishAsync(new TestMessage2 { Id = 3 }); await Task.Delay(TimeSpan.FromSeconds(2)); + sub.Dispose(); + source.Dispose(); + publisher.Dispose(); + Assert.True(messages.OfType().Any(msg => msg.Id == 1), "TestMessage1 1 not received"); Assert.True(messages.OfType().Any(msg => msg.Id == 2), "TestMessage1 2 not received"); Assert.True(messages.OfType().Any(msg => msg.Id == 3), "TestMessage1 3 not received"); @@ -57,9 +63,6 @@ public async Task TestSendingAndReceivingStringsOverLocalHost() Assert.True(messages.OfType().Any(msg => msg.Id == 1), "TestMessage2 1 not received"); Assert.True(messages.OfType().Any(msg => msg.Id == 2), "TestMessage2 2 not received"); Assert.True(messages.OfType().Any(msg => msg.Id == 3), "TestMessage2 3 not received"); - - sub.Dispose(); - source.Dispose(); } [Fact, Trait("Category", "Explicit")] @@ -76,7 +79,7 @@ public async Task TestSendingAndReceivingBytesOverLocalHost() }, err => Console.WriteLine("Error: " + err)); - IMessageSource source = new MessageSource("tcp://localhost:5556", + IMessageSource source = new MessageSource("tcp://localhost:5561", new IMessageDeserializer[] { new ProtoBufMessageDeserializer(), @@ -86,7 +89,7 @@ public async Task TestSendingAndReceivingBytesOverLocalHost() var sub = source.Messages.Subscribe(observer); - IMessagePublisher publisher = new MessagePublisher("tcp://localhost:5556", + IMessagePublisher publisher = new MessagePublisher("tcp://localhost:5561", new ProtoBufMessageSerializer(), topic); await publisher.PublishAsync(new TestMessage1 { Id = 1 }); @@ -97,6 +100,10 @@ public async Task TestSendingAndReceivingBytesOverLocalHost() await publisher.PublishAsync(new TestMessage2 { Id = 3 }); await Task.Delay(TimeSpan.FromSeconds(2)); + sub.Dispose(); + source.Dispose(); + publisher.Dispose(); + Assert.True(messages.OfType().Any(msg => msg.Id == 1), "TestMessage1 1 not received"); Assert.True(messages.OfType().Any(msg => msg.Id == 2), "TestMessage1 2 not received"); Assert.True(messages.OfType().Any(msg => msg.Id == 3), "TestMessage1 3 not received"); @@ -104,9 +111,6 @@ public async Task TestSendingAndReceivingBytesOverLocalHost() Assert.True(messages.OfType().Any(msg => msg.Id == 1), "TestMessage2 1 not received"); Assert.True(messages.OfType().Any(msg => msg.Id == 2), "TestMessage2 2 not received"); Assert.True(messages.OfType().Any(msg => msg.Id == 3), "TestMessage2 3 not received"); - - sub.Dispose(); - source.Dispose(); } [Fact, Trait("Category", "Explicit")] @@ -117,8 +121,10 @@ public async Task TestMessagesLongerThan32Characters() const string topic = "TestTopicxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; IDisposable sub; + MessageSource source; + MessagePublisher publisher; { - var source = new MessageSource("tcp://localhost:5557", + source = new MessageSource("tcp://localhost:5562", new IMessageDeserializer[] { new ProtoBufMessageDeserializer(), @@ -134,7 +140,7 @@ public async Task TestMessagesLongerThan32Characters() } { - var publisher = new MessagePublisher("tcp://localhost:5557", + publisher = new MessagePublisher("tcp://localhost:5562", new ProtoBufMessageSerializer(), topic); @@ -150,6 +156,8 @@ await publisher.PublishAsync(new TestMessageWhereTypeIsVeryMuchDefinitionLongerT await Task.Delay(TimeSpan.FromSeconds(2)); sub.Dispose(); + source.Dispose(); + publisher.Dispose(); } [ProtoContract] diff --git a/Obvs.NetMQ.Tests/TestServiceBusWithNetMq.cs b/Obvs.NetMQ.Tests/TestServiceBusWithNetMq.cs index 851819c8..721e3e21 100644 --- a/Obvs.NetMQ.Tests/TestServiceBusWithNetMq.cs +++ b/Obvs.NetMQ.Tests/TestServiceBusWithNetMq.cs @@ -141,6 +141,11 @@ public async Task TestServiceEndpointsOverLocalHostSockets() // wait some time until we think all messages have been sent and received await Task.Delay(TimeSpan.FromSeconds(3)); + // dispose before asserting, so a failed assertion doesn't leave sockets bound for other tests + ((IDisposable)serviceBus).Dispose(); + ((IDisposable)serviceBusClient1).Dispose(); + ((IDisposable)serviceBusClient2).Dispose(); + // test we got everything we expected Assert.True(messages.OfType().Count() == 2, "TestCommand1"); Assert.True(messages.OfType().Count() == 4, "TestEvent1");