using Microsoft.Extensions.Logging.Abstractions; using ZB.MOM.WW.ScadaBridge.Commons.Messages.Scripting; using ZB.MOM.WW.ScadaBridge.Host.Services; namespace ZB.MOM.WW.ScadaBridge.Host.Tests; /// /// #05-T14: unit tests for the in-process script-artifact change bus — delivery, /// unsubscribe, and the swallow-and-log guard that keeps a faulting subscriber from /// faulting the producer. /// public sealed class InProcessScriptArtifactChangeBusTests { private static InProcessScriptArtifactChangeBus NewBus() => new(NullLogger.Instance); private static ScriptArtifactsChanged Sample(string kind = ScriptArtifactKinds.ApiMethod) => new(kind, new[] { "M1" }, "Management", DateTimeOffset.UnixEpoch); [Fact] public void Publish_delivers_to_all_current_subscribers() { var bus = NewBus(); var a = new List(); var b = new List(); bus.Subscribe(a.Add); bus.Subscribe(b.Add); var n = Sample(); bus.Publish(n); Assert.Same(n, Assert.Single(a)); Assert.Same(n, Assert.Single(b)); } [Fact] public void Disposing_subscription_stops_delivery() { var bus = NewBus(); var received = new List(); var token = bus.Subscribe(received.Add); bus.Publish(Sample()); token.Dispose(); bus.Publish(Sample()); Assert.Single(received); // only the pre-dispose publish landed. } [Fact] public void Dispose_is_idempotent() { var bus = NewBus(); var received = new List(); var token = bus.Subscribe(received.Add); token.Dispose(); token.Dispose(); // must not throw nor corrupt the handler list. bus.Publish(Sample()); Assert.Empty(received); } [Fact] public void A_faulting_subscriber_does_not_prevent_delivery_to_others_nor_throw() { var bus = NewBus(); var good = new List(); bus.Subscribe(_ => throw new InvalidOperationException("bad consumer")); bus.Subscribe(good.Add); // Publish must not propagate the subscriber fault... var ex = Record.Exception(() => bus.Publish(Sample())); Assert.Null(ex); // ...and the well-behaved subscriber still receives it. Assert.Single(good); } [Fact] public void Publish_with_no_subscribers_is_a_noop() { var bus = NewBus(); Assert.Null(Record.Exception(() => bus.Publish(Sample()))); } }