using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging.Abstractions; using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Configuration.LocalCache; namespace ZB.MOM.WW.OtOpcUa.Server.Tests; /// /// Regression for Server-014 — exists in the source tree and /// is referenced by docs/v2/v2-release-readiness.md as the closed release blocker for /// generation-sealed config plumbing, but it was never registered in the production DI /// container. The release blocker remained de-facto open. This test asserts the DI /// registrations (which Program.cs performs at startup) actually compose: every /// dependency needs — , /// , — must be resolvable /// so the production wire-up doesn't fail with a missing-service exception at startup. /// [Trait("Category", "Unit")] public sealed class SealedBootstrapWiringTests { [Fact] public void SealedBootstrap_and_its_dependencies_are_registered_in_DI() { var tempRoot = Path.Combine(Path.GetTempPath(), $"otopcua-sealed-bootstrap-wiring-{Guid.NewGuid():N}"); try { // Mirror Program.cs's registrations of NodeOptions + the SealedBootstrap chain. var services = new ServiceCollection(); ZB.MOM.WW.OtOpcUa.Server.ServerWiring.AddSealedBootstrap(services, new NodeOptions { NodeId = "test-node", ClusterId = "test-cluster", ConfigDbConnectionString = "Server=fake;Database=fake;Integrated Security=true;", LocalCachePath = tempRoot, }); services.AddSingleton(NullLoggerFactory.Instance); services.AddLogging(); using var sp = services.BuildServiceProvider(); sp.GetRequiredService().ShouldNotBeNull(); sp.GetRequiredService().ShouldNotBeNull(); sp.GetRequiredService().ShouldNotBeNull(); sp.GetRequiredService().ShouldNotBeNull(); } finally { try { if (Directory.Exists(tempRoot)) Directory.Delete(tempRoot, recursive: true); } catch { } } } }