示例#1
0
        public async Task Given_responder_exists_When_requesting_using_string_It_should_get_response()
        {
            var value = Guid.NewGuid().ToString("N");

            _responder.Sub("getValue", stream => stream.Subscribe(msg => _responder.Pub(msg.ReplyTo, msg.GetPayloadAsString())));

            var response = await _requester.RequestAsync("getValue", value);

            response.GetPayloadAsString().Should().Be(value);
        }
示例#2
0
        public async Task Client_Should_be_able_to_unsub_from_a_subject()
        {
            var subject     = Context.GenerateSubject();
            var nr1Received = new ConcurrentQueue <MsgOp>();
            var nr2Received = new ConcurrentQueue <MsgOp>();
            var nr3Received = new ConcurrentQueue <MsgOp>();
            var subInfo1    = new SubscriptionInfo(subject);
            var subInfo2    = new SubscriptionInfo(subject);
            var subInfo3    = new SubscriptionInfo(subject);

            _sync = Sync.MaxThree();
            await ConnectAllClients();

            _client1.OpStream.OfType <MsgOp>().Subscribe(msg =>
            {
                _client1.Unsub(subInfo1);
                nr1Received.Enqueue(msg);
                _sync.Release(msg);
            });
            _client1.Sub(subInfo1);

            _client2.OpStream.OfType <MsgOp>().Subscribe(async msg =>
            {
                await _client2.UnsubAsync(subInfo2);
                nr2Received.Enqueue(msg);
                _sync.Release(msg);
            });
            _client2.Sub(subInfo2);

            _client3.OpStream.OfType <MsgOp>().Subscribe(msg =>
            {
                nr3Received.Enqueue(msg);
                _sync.Release(msg);
            });
            _client3.Sub(subInfo3);

            await Context.DelayAsync();

            _client1.Pub(subject, "mess1");
            _sync.WaitForAll();

            _client3.Unsub(subInfo3);
            await Context.DelayAsync();

            _client1.Pub(subject, "mess2");
            await Context.DelayAsync();

            _sync.InterceptedCount.Should().Be(3);
            nr1Received.Should().HaveCount(1);
            nr2Received.Should().HaveCount(1);
            nr3Received.Should().HaveCount(1);
        }
示例#3
0
        public async Task Client_Should_be_able_to_unsub_from_a_subject()
        {
            const string subject         = "Test";
            var          nr1ReceiveCount = 0;
            var          nr2ReceiveCount = 0;
            var          nr3ReceiveCount = 0;
            var          subInfo1        = new SubscriptionInfo(subject);
            var          subInfo2        = new SubscriptionInfo(subject);
            var          subInfo3        = new SubscriptionInfo(subject);

            _client1.OpStream.OfType <MsgOp>().Subscribe(msg =>
            {
                _client1.Unsub(subInfo1);
                Interlocked.Increment(ref nr1ReceiveCount);
                ReleaseOne();
            });
            _client1.Sub(subInfo1);

            _client2.OpStream.OfType <MsgOp>().Subscribe(async msg =>
            {
                await _client2.UnsubAsync(subInfo2);
                Interlocked.Increment(ref nr2ReceiveCount);
                ReleaseOne();
            });
            _client2.Sub(subInfo2);

            _client3.OpStream.OfType <MsgOp>().Subscribe(msg =>
            {
                Interlocked.Increment(ref nr3ReceiveCount);
                ReleaseOne();
            });
            _client3.Sub(subInfo3);

            _client1.Pub(subject, "mess1");
            WaitOne();
            WaitOne();
            WaitOne();

            _client3.Unsub(subInfo3);
            await DelayAsync();

            _client1.Pub(subject, "mess2");
            await DelayAsync();

            nr1ReceiveCount.Should().Be(1);
            nr2ReceiveCount.Should().Be(1);
            nr3ReceiveCount.Should().Be(1);
        }
示例#4
0
        public async Task Client_Should_throw_if_request_after_disconnected()
        {
            var subject = Context.GenerateSubject();
            var body    = new byte[0];

            _responder = await Context.ConnectClientAsync();

            _requester = await Context.ConnectClientAsync();

            _responder.Sub(subject, stream => stream.Subscribe(msg => _responder.Pub(msg.ReplyTo, msg.GetPayloadAsString())));

            await Context.DelayAsync();

            // Succeeds
            var response = await _requester.RequestAsync(subject, "body");

            Assert.NotNull(response);

            response = await _requester.RequestAsync(subject, body.AsMemory());

            Assert.NotNull(response);

            // Disconnect from NATS per user request
            _requester.Disconnect();
            Assert.False(_requester.IsConnected);

            // Fails after being disconnected
            await Should.ThrowNatsExceptionAsync(() => _requester.RequestAsync(subject, "body"));

            await Should.ThrowNatsExceptionAsync(() => _requester.RequestAsync(subject, body.AsMemory()));
        }
示例#5
0
        public async Task Given_multiple_responders_exists_When_requesting_It_should_return_one_response()
        {
            var value = Guid.NewGuid().ToString("N");
            var responderReplyingCount = 0;
            var responderReplyCount    = 0;

            _requester.MsgOpStream.Subscribe(msgOp => Interlocked.Increment(ref responderReplyCount));

            _responder.Sub("getValue", stream => stream.Subscribe(msg =>
            {
                Interlocked.Increment(ref responderReplyingCount);
                _responder.Pub(msg.ReplyTo, msg.GetPayloadAsString());
            }));

            MsgOp response;

            using (var responder2 = new NatsClient(ConnectionInfo))
            {
                responder2.Connect();
                responder2.Sub("getValue", stream => stream.Subscribe(msg =>
                {
                    Interlocked.Increment(ref responderReplyingCount);
                    responder2.Pub(msg.ReplyTo, msg.GetPayloadAsString());
                }));

                response = await _requester.RequestAsync("getValue", value);
            }

            response.GetPayloadAsString().Should().Be(value);
            responderReplyCount.Should().Be(1);
            responderReplyingCount.Should().Be(2);
        }
示例#6
0
        public async Task Client_Should_be_able_to_publish_and_consume_messages_When_publishing_batch()
        {
            var subject  = Context.GenerateSubject();
            var messages = new[]
            {
                "My test string\r\nwith two lines and\ttabs!",
                "Foo bar!",
                "My async test string\r\nwith two lines and\ttabs!",
                "Async Foo bar!"
            };

            _sync    = Sync.Max(4);
            _client1 = await Context.ConnectClientAsync();

            _client1.MsgOpStream.Subscribe(msg => _sync.Release(msg));
            _client1.Sub(subject);

            await Context.DelayAsync();

            _client1.PubMany(async p =>
            {
                p.Pub(subject, messages[0]);
                p.Pub(subject, Encoding.UTF8.GetBytes(messages[1]));
                await p.PubAsync(subject, messages[2]);
                await p.PubAsync(subject, Encoding.UTF8.GetBytes(messages[3]));
            });

            _sync.WaitForAll();
            _sync.InterceptedCount.Should().Be(messages.Length);
            _sync.Intercepted.Select(m => m.GetPayloadAsString()).ToArray().Should().Contain(messages);
        }
示例#7
0
        public async Task Given_subscribed_sync_using_handler_When_the_subscription_has_been_disposed_It_should_not_get_messages()
        {
            var subject = Context.GenerateSubject();

            _sync   = Sync.MaxOne();
            _client = await Context.ConnectClientAsync();

            var s = _client.Sub(subject, stream => stream.Subscribe(msg => _sync.Release(msg)));

            await Context.DelayAsync();

            await _client.PubAsync(subject, "Test1");

            _sync.WaitForAny();
            await _client.PubAsync(subject, "Test2");

            _sync.WaitForAny();

            s.Dispose();

            await _client.PubAsync(subject, "Test3");

            await Context.DelayAsync();

            _sync.InterceptedCount.Should().Be(2);
        }
示例#8
0
        public async Task Given_subscribed_When_unsubscribing_async_It_should_not_get_any_further_messages()
        {
            var subject = Context.GenerateSubject();

            _sync   = Sync.MaxOne();
            _client = await Context.ConnectClientAsync();

            var s = _client.Sub(subject, stream => stream.Subscribe(NatsObserver.Delegating <MsgOp>(msg => _sync.Release(msg))));

            await Context.DelayAsync();

            await _client.PubAsync(subject, "Test1");

            _sync.WaitForAny();
            await _client.PubAsync(subject, "Test2");

            _sync.WaitForAny();

            await _client.UnsubAsync(s.SubscriptionInfo);

            await _client.PubAsync(subject, "Test3");

            await Context.DelayAsync();

            _sync.InterceptedCount.Should().Be(2);
        }
示例#9
0
        public async Task Client_Should_dispatch_to_all_subscribed_clients()
        {
            const string subject         = "Test";
            var          nr2ReceiveCount = 0;
            var          nr3ReceiveCount = 0;

            _client2.OpStream.OfType <MsgOp>().Subscribe(msg =>
            {
                Interlocked.Increment(ref nr2ReceiveCount);
                ReleaseOne();
            });
            _client2.Sub(subject);

            _client3.OpStream.OfType <MsgOp>().Subscribe(msg =>
            {
                Interlocked.Increment(ref nr3ReceiveCount);
                ReleaseOne();
            });
            await _client3.SubAsync(subject);

            _client1.Pub(subject, "mess1");
            WaitOne();
            WaitOne();

            await _client1.PubAsync(subject, "mess2");

            WaitOne();
            WaitOne();

            nr2ReceiveCount.Should().Be(2);
            nr3ReceiveCount.Should().Be(2);
        }
示例#10
0
        public async Task Client_Should_be_able_to_publish_and_consume_messages_When_publishing_one_by_one()
        {
            var interceptCount = 0;
            var intercepted    = new List <MsgOp>();
            var messages       = new[]
            {
                "My test string\r\nwith two lines and\ttabs!",
                "Foo bar!",
                "My async test string\r\nwith two lines and\ttabs!",
                "Async Foo bar!"
            };

            _client1.MsgOpStream.Subscribe(msg =>
            {
                intercepted.Add(msg);
                var x = Interlocked.Increment(ref interceptCount);
                if (x == messages.Length)
                {
                    ReleaseOne();
                }
            });
            _client1.Sub("Test");

            _client1.Pub("Test", messages[0]);
            _client1.Pub("Test", Encoding.UTF8.GetBytes(messages[1]));
            await _client1.PubAsync("Test", messages[2]);

            await _client1.PubAsync("Test", Encoding.UTF8.GetBytes(messages[3]));

            WaitOne();
            intercepted.Should().HaveCount(messages.Length);
            intercepted.Select(m => m.GetPayloadAsString()).ToArray().Should().Contain(messages);
        }
示例#11
0
        public void Given_not_connected_Should_be_able_to_subscribe()
        {
            _client = Context.CreateClient();

            var sub = _client.Sub(Context.GenerateSubject());

            sub.Should().NotBeNull();
            _client.IsConnected.Should().BeFalse();
        }
示例#12
0
        public async Task Client_Should_be_able_to_subscribe_to_the_same_subject_twice()
        {
            var subject = Context.GenerateSubject();

            _sync    = Sync.MaxTwo();
            _client1 = await Context.ConnectClientAsync();

            _client1.OpStream.OfType <MsgOp>().Subscribe(msg => _sync.Release(msg));
            _client1.Sub(subject);
            _client1.Sub(subject);

            await Context.DelayAsync();

            _client1.Pub(subject, "mess1");
            _sync.WaitForAll();

            _sync.InterceptedCount.Should().Be(2);
        }
示例#13
0
        public async Task Client_Should_be_able_to_subscribe_to_many_subjects()
        {
            var subject1 = Context.GenerateSubject();
            var subject2 = Context.GenerateSubject();

            _sync    = Sync.MaxTwo();
            _client1 = await Context.ConnectClientAsync();

            _client1.OpStream.OfType <MsgOp>().Where(m => m.Subject == subject1).Subscribe(msg => _sync.Release(msg));
            _client1.OpStream.OfType <MsgOp>().Where(m => m.Subject == subject2).Subscribe(msg => _sync.Release(msg));
            _client1.Sub(subject1);
            _client1.Sub(subject2);

            await Context.DelayAsync();

            _client1.Pub(subject1, "mess1");
            _client1.Pub(subject2, "mess2");
            _sync.WaitForAll();

            _sync.InterceptedCount.Should().Be(2);
        }
示例#14
0
        public async Task Given_multiple_responders_exists_and_non_inbox_requests_are_used_When_requesting_It_should_call_requester_once_and_dispatch_one_response()
        {
            _sync = Sync.MaxTwo();

            var cnInfoResponder = Context.GetConnectionInfo();
            var cnInfoRequester = cnInfoResponder.Clone();

            cnInfoRequester.UseInboxRequests = false;

            var value             = Guid.NewGuid().ToString("N");
            var responderReceived = new ConcurrentQueue <MsgOp>();
            var requesterReceived = new ConcurrentQueue <MsgOp>();
            var responsesReceived = new ConcurrentQueue <MsgOp>();

            _responder = await Context.ConnectClientAsync(cnInfoResponder);

            _requester = await Context.ConnectClientAsync(cnInfoRequester);

            _requester.MsgOpStream.Subscribe(msgOp => requesterReceived.Enqueue(msgOp));

            _responder.Sub("getValue", stream => stream.Subscribe(msg =>
            {
                responderReceived.Enqueue(msg);
                _responder.Pub(msg.ReplyTo, msg.GetPayloadAsString());
                _sync.Release();
            }));

            using (var responder2 = new NatsClient(cnInfoResponder))
            {
                await responder2.ConnectAsync();

                responder2.Sub("getValue", stream => stream.Subscribe(msg =>
                {
                    responderReceived.Enqueue(msg);
                    responder2.Pub(msg.ReplyTo, msg.GetPayloadAsString());
                    _sync.Release();
                }));

                await Context.DelayAsync();

                var response = await _requester.RequestAsync("getValue", value);

                responsesReceived.Enqueue(response);
            }

            _sync.WaitForAll();

            responsesReceived.Should().HaveCount(1);
            requesterReceived.Should().HaveCount(1);
            responderReceived.Should().HaveCount(2);
            responsesReceived.First().GetPayloadAsString().Should().Be(value);
        }
示例#15
0
        public async Task Given_subscribed_sync_using_handler_and_subscribed_to_other_subject_as_well_It_should_only_get_subject_specific_messages()
        {
            var subject                  = Context.GenerateSubject();
            var otherSubject             = subject + "fail";
            var interceptedSubjects      = new List <string>();
            var interceptedOtherSubjects = new List <string>();

            _sync   = Sync.MaxTwo();
            _client = await Context.ConnectClientAsync();

            _client.Sub(subject, stream => stream.Subscribe(msg =>
            {
                interceptedSubjects.Add(msg.Subject);
                _sync.Release();
            }));
            _client.Sub(otherSubject, stream => stream.Subscribe(msg =>
            {
                interceptedOtherSubjects.Add(msg.Subject);
                _sync.Release();
            }));

            await Context.DelayAsync();

            await _client.PubAsync(subject, "Test1");

            _sync.WaitForAny();
            await _client.PubAsync(subject, "Test2");

            _sync.WaitForAny();
            await _client.PubAsync(otherSubject, "Test3");

            _sync.WaitForAny();

            interceptedSubjects.Should().HaveCount(2);
            interceptedSubjects.Should().OnlyContain(i => i == subject);
            interceptedOtherSubjects.Should().HaveCount(1);
            interceptedOtherSubjects.Should().OnlyContain(i => i == otherSubject);
        }
示例#16
0
        public async Task Given_responder_exists_When_requesting_using_bytes_It_should_get_response()
        {
            var value = Guid.NewGuid().ToString("N");

            _responder = await Context.ConnectClientAsync();

            _requester = await Context.ConnectClientAsync();

            _responder.Sub("getValue", stream => stream.Subscribe(msg => _responder.Pub(msg.ReplyTo, msg.GetPayloadAsString())));

            await Context.DelayAsync();

            var response = await _requester.RequestAsync("getValue", Encoding.UTF8.GetBytes(value));

            response.GetPayloadAsString().Should().Be(value);
        }
        public void Should_be_able_to_publish_and_consume_JSON_payloads_synchronously()
        {
            var orgItem = EncodingTestItem.Create();
            EncodingTestItem decodedItem = null;

            _client.Sub("ClientProtobufEncodingTests", stream => stream.Subscribe(msg =>
            {
                decodedItem = msg.FromJson <EncodingTestItem>();
                ReleaseOne();
            }));

            _client.PubAsJson("ClientProtobufEncodingTests", orgItem);
            WaitOne();

            orgItem.Should().BeEquivalentTo(decodedItem);
        }
示例#18
0
        static async Task Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            // hit ctrl-C to close/exit

            var cts = new CancellationTokenSource();

            Console.CancelKeyPress += (_, e) =>
            {
                Console.WriteLine("cancelled...");
                cts.Cancel();
                e.Cancel = true;
            };

            var sp = ConfigureServices();

            var client = new ClientBuilder(sp)
                         .UseSockets()
                         //.UseConnectionLogging()
                         .Build();

            var conn = await client.ConnectAsync(new IPEndPoint(IPAddress.Loopback, 4222));

            var nats = new NatsClient();
            await nats.ConnectAsync(new IPEndPoint(IPAddress.Loopback, 4222), sp);

            // test this with "pub test2 2\r\nhi" from telnet
            nats.Sub("test2", "1", msg =>
            {
                var text = Encoding.UTF8.GetString(msg.Data.Span);
                Console.WriteLine($"OnMsg: subject:{msg.Subject} sid:{msg.Sid} replyto:{msg.ReplyTo} text:{text}");
            });

            // test this with "sub test1 1" from telnet
            while (!cts.Token.IsCancellationRequested)
            {
                Console.WriteLine("pub...");
                nats.Pub("test1", Encoding.UTF8.GetBytes("hello"));
                await Task.Delay(2000);
            }

            Console.WriteLine("done...");
            Console.ReadLine();
        }
示例#19
0
        public async Task Given_responder_exists_When_requesting_using_string_It_should_get_response()
        {
            var value = Guid.NewGuid().ToString("N");

            var connectionInfo = Context
                                 .GetConnectionInfo()
                                 .AllowAllServerCertificates();

            _responder = await Context.ConnectClientAsync(connectionInfo);

            _requester = await Context.ConnectClientAsync(connectionInfo);

            _responder.Sub("getValue", stream => stream.Subscribe(msg => _responder.Pub(msg.ReplyTo, msg.GetPayloadAsString())));

            var response = await _requester.RequestAsync("getValue", value);

            response.GetPayloadAsString().Should().Be(value);
        }
示例#20
0
        public async Task Client_Should_dispatch_to_all_subscribed_clients()
        {
            var subject    = Context.GenerateSubject();
            var nr1Receive = new ConcurrentQueue <MsgOp>();
            var nr2Receive = new ConcurrentQueue <MsgOp>();
            var nr3Receive = new ConcurrentQueue <MsgOp>();

            _sync    = Sync.MaxTwo();
            _client1 = await Context.ConnectClientAsync();

            _client2 = await Context.ConnectClientAsync();

            _client3 = await Context.ConnectClientAsync();

            _client1.OpStream.OfType <MsgOp>().Subscribe(msg => nr1Receive.Enqueue(msg));

            _client2.OpStream.OfType <MsgOp>().Subscribe(msg =>
            {
                nr2Receive.Enqueue(msg);
                _sync.Release(msg);
            });
            _client2.Sub(subject);

            _client3.OpStream.OfType <MsgOp>().Subscribe(msg =>
            {
                nr3Receive.Enqueue(msg);
                _sync.Release(msg);
            });
            await _client3.SubAsync(subject);

            await Context.DelayAsync();

            _client1.Pub(subject, "mess1");
            _sync.WaitForAll();

            await _client1.PubAsync(subject, "mess2");

            _sync.WaitForAll();

            _sync.InterceptedCount.Should().Be(4);
            nr1Receive.Count.Should().Be(0);
            nr2Receive.Count.Should().Be(2);
            nr3Receive.Count.Should().Be(2);
        }
        public async Task Should_be_able_to_publish_and_consume_JSON_payloads_synchronously()
        {
            var subject = Context.GenerateSubject();
            var orgItem = EncodingTestItem.Create();
            EncodingTestItem decodedItem = null;

            _sync   = Sync.MaxOne();
            _client = await Context.ConnectClientAsync();

            _client.Sub(subject, stream => stream.Subscribe(msg =>
            {
                decodedItem = msg.FromJson <EncodingTestItem>();
                _sync.Release();
            }));

            _client.PubAsJson(subject, orgItem);
            _sync.WaitForAll();

            orgItem.Should().BeEquivalentTo(decodedItem);
        }
示例#22
0
        public async Task Given_subscribed_with_wildcard_sync_using_handler_It_should_get_messages()
        {
            const string subjectNs = "foo.tests.";

            _sync   = Sync.MaxOne();
            _client = await Context.ConnectClientAsync();

            _client.Sub(subjectNs + "*", stream => stream.Subscribe(msg => _sync.Release(msg)));

            await Context.DelayAsync();

            await _client.PubAsync(subjectNs + "type1", "Test1");

            _sync.WaitForAny();
            await _client.PubAsync(subjectNs + "type2", "Test2");

            _sync.WaitForAny();
            await _client.PubAsync(subjectNs + "type3", "Test3");

            _sync.WaitForAny();

            _sync.InterceptedCount.Should().Be(3);
            _sync.Intercepted.Select(i => i.Subject).Should().OnlyContain(i => i.StartsWith(subjectNs));
        }
示例#23
0
        public async Task Given_subscribed_When_disconnectiong_and_connecting_again_It_should_resubscribe_and_get_messages()
        {
            var subject = Context.GenerateSubject();

            _sync   = Sync.MaxOne();
            _client = await Context.ConnectClientAsync();

            _client.Sub(subject, stream => stream.Subscribe(NatsObserver.Delegating <MsgOp>(msg => _sync.Release(msg))));

            await Context.DelayAsync();

            await _client.PubAsync(subject, "Test1");

            _sync.WaitForAny();
            _client.Disconnect();

            await _client.ConnectAsync();

            await _client.PubAsync(subject, "Test2");

            _sync.WaitForAny();

            _sync.InterceptedCount.Should().Be(2);
        }
示例#24
0
        public static async Task <TimeSpan> MyNatsClientRequestAsync(int n, ReadOnlyMemory <byte> payload, bool useTls)
        {
            Console.WriteLine($"MyNatsClient-RequestAsync: n={n} s={payload.Length}");

            const string subject = "casea";

            using var cts  = new CancellationTokenSource();
            using var sync = new AutoResetEvent(false);
            var tcs    = new TaskCompletionSource <TimeSpan>();
            var cnInfo = new ConnectionInfo("127.0.0.1");

            if (useTls)
            {
                cnInfo.ServerCertificateValidation = (_, __, ___) => true;
            }

            var responderTask = Task.Factory.StartNew(async() =>
            {
                using var client = new NatsClient(cnInfo);
                await client.ConnectAsync().ConfigureAwait(false);

                client.Sub(subject, messages => messages.SubscribeSafe(msg => { client.Pub(msg.ReplyTo, msg.Payload); }));

                sync.Set();

                await tcs.Task.ConfigureAwait(false);
            }, cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);

            var requesterTask = Task.Factory.StartNew(async() =>
            {
                using var client = new NatsClient(cnInfo);

                await client.ConnectAsync().ConfigureAwait(false);

                if (!sync.WaitOne(1000))
                {
                    throw new Exception("Responder does not seem to be started.");
                }

                for (var i = 0; i < 10; i++)
                {
                    await client.RequestAsync(subject, payload, cts.Token).ConfigureAwait(false);
                }

                var sw = Stopwatch.StartNew();

                for (var i = 0; i < n; i++)
                {
                    await client.RequestAsync(subject, payload, cts.Token).ConfigureAwait(false);
                }

                sw.Stop();
                tcs.SetResult(sw.Elapsed);
            }, cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);

            var elapsed = await tcs.Task.ConfigureAwait(false);

            cts.Cancel();

            await Task.WhenAll(responderTask, requesterTask).ConfigureAwait(false);

            return(elapsed);
        }
示例#25
0
        public async Task Given_subscribed_sync_using_observer_and_subscribed_to_other_subject_as_well_It_should_only_get_subject_specific_messages()
        {
            var subject             = GenerateSubject();
            var otherSubject        = subject + "fail";
            var interceptedSubjects = new List <string>();

            _client.Sub(subject, stream => stream.Subscribe(msg =>
            {
                interceptedSubjects.Add(msg.Subject);
                ReleaseOne();
            }));
            _client.Sub(otherSubject, stream => stream.Subscribe(msg => ReleaseOne()));

            await _client.PubAsync(subject, "Test1");

            WaitOne();
            await _client.PubAsync(subject, "Test2");

            WaitOne();
            await _client.PubAsync(otherSubject, "Test3");

            WaitOne();

            interceptedSubjects.Should().HaveCount(2);
            interceptedSubjects.Should().OnlyContain(i => i == subject);
        }