using Microsoft.Extensions.DependencyInjection; using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Core.Abstractions; using ZB.MOM.WW.OtOpcUa.Core.Resilience; using ZB.MOM.WW.OtOpcUa.Host.Drivers; namespace ZB.MOM.WW.OtOpcUa.Host.IntegrationTests; /// /// Guards the production DI wiring for the Phase 6.1 resilience dispatch pipeline (arch-review #10 + /// #13). AddOtOpcUaDriverFactories (the driver-node bootstrap) must bind the real /// — not the /// pass-through — and that factory must mint a real per driver instance. /// This is the DI half of the #10 live gate: without it a refactor could silently drop back to the /// pass-through and the retry/breaker/bulkhead pipeline would go inert in production (the exact /// "built-but-never-wired" failure the whole review targets), while every unit test — which defaults to /// the pass-through — stays green. /// public sealed class ResilienceInvokerFactoryRegistrationTests { [Fact] public void AddOtOpcUaDriverFactories_binds_the_real_invoker_factory_not_the_pass_through() { var services = new ServiceCollection(); services.AddLogging(); services.AddOtOpcUaDriverFactories(); using var sp = services.BuildServiceProvider(); var factory = sp.GetRequiredService(); factory.ShouldBeOfType( "the driver-node bootstrap must bind the real resilience factory — a NullDriverCapabilityInvokerFactory here means the pipeline is inert in production"); } [Fact] public void The_registered_factory_mints_a_real_CapabilityInvoker_per_instance() { var services = new ServiceCollection(); services.AddLogging(); services.AddOtOpcUaDriverFactories(); using var sp = services.BuildServiceProvider(); var factory = sp.GetRequiredService(); var invoker = factory.Create("drv-1", "Modbus"); invoker.ShouldBeOfType( "the real factory must produce a real CapabilityInvoker (not the NullDriverCapabilityInvoker pass-through)"); } [Fact] public void The_resilience_singletons_the_factory_depends_on_are_registered() { var services = new ServiceCollection(); services.AddLogging(); services.AddOtOpcUaDriverFactories(); using var sp = services.BuildServiceProvider(); // The pipeline builder + status tracker are process singletons the factory closes over — the same // instance must be shared so pipelines cache + telemetry aggregate across all driver instances. sp.GetService().ShouldNotBeNull(); sp.GetService().ShouldNotBeNull(); sp.GetRequiredService() .ShouldBeSameAs(sp.GetRequiredService(), "builder must be a singleton"); } }