using Akka.Actor; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using ZB.MOM.WW.ScadaBridge.ClusterInfrastructure; using ZB.MOM.WW.ScadaBridge.Communication; using ZB.MOM.WW.ScadaBridge.Host; using ZB.MOM.WW.ScadaBridge.Host.Actors; namespace ZB.MOM.WW.ScadaBridge.Host.Tests; /// /// Verifies the DI bridge that exposes the Akka — owned by /// , not registered as a DI singleton — to consumers that /// resolve ActorSystem from the container (notably the shared ZB.MOM.WW.Health Akka /// checks). The bridge is registered TRANSIENT so each resolve re-reads the current value: /// null while the hosted service is warming up (checks treat that as Degraded), the live /// system afterwards. A SINGLETON would cache the startup-time null forever. /// public sealed class ActorSystemBridgeTests { [Fact] public void ActorSystem_ResolvesNull_BeforeHostedServiceStarts() { var services = new ServiceCollection(); // Register AkkaHostedService the same way Program.cs does, supplying the minimal // constructor dependencies so the container can build it. Its ActorSystem property // is null until StartAsync runs — which it never does here. services.AddSingleton(Options.Create(new NodeOptions())); services.AddSingleton(Options.Create(new ClusterOptions())); services.AddSingleton(Options.Create(new CommunicationOptions())); services.AddSingleton>(NullLogger.Instance); services.AddSingleton(); // The bridge under test: TRANSIENT factory that re-reads the owned ActorSystem. services.AddTransient(sp => sp.GetRequiredService().ActorSystem!); using var provider = services.BuildServiceProvider(); // The hosted service has not started, so the bridge must yield null (not throw). Assert.Null(provider.GetService()); } }