test(secrets): register ISecretResolver in driver-factory resilience tests (Task 10 fix)
v2-ci / build (push) Successful in 3m36s
v2-ci / unit-tests (push) Failing after 8m35s

The full-suite gate caught a real regression: AddOtOpcUaDriverFactories' registration
now resolves ISecretResolver (for Galaxy/OpcUaClient secret: refs, Tasks 7-8), so the
two ResilienceInvokerFactoryRegistrationTests that build a minimal container and resolve
the invoker factory threw 'No service for ISecretResolver'. The real host always
registers it via AddZbSecrets (unconditional, Task 3), and GetRequiredService correctly
fails-fast for a genuinely misconfigured host — so the fix is to complete the test
container with a stub resolver, matching production composition. Test-only.
This commit is contained in:
Joseph Doherty
2026-07-16 18:27:59 -04:00
parent f1534920de
commit 872cf7e37a
@@ -4,6 +4,7 @@ using Xunit;
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
using ZB.MOM.WW.OtOpcUa.Core.Resilience;
using ZB.MOM.WW.OtOpcUa.Host.Drivers;
using ZB.MOM.WW.Secrets.Abstractions;
namespace ZB.MOM.WW.OtOpcUa.Host.IntegrationTests;
@@ -24,6 +25,9 @@ public sealed class ResilienceInvokerFactoryRegistrationTests
{
var services = new ServiceCollection();
services.AddLogging();
// The driver-factory registration resolves ISecretResolver (Galaxy/OpcUaClient secret: refs);
// the real host always has it via AddZbSecrets (registered unconditionally). Mirror that here.
services.AddSingleton<ISecretResolver>(new StubSecretResolver());
services.AddOtOpcUaDriverFactories();
using var sp = services.BuildServiceProvider();
@@ -38,6 +42,9 @@ public sealed class ResilienceInvokerFactoryRegistrationTests
{
var services = new ServiceCollection();
services.AddLogging();
// The driver-factory registration resolves ISecretResolver (Galaxy/OpcUaClient secret: refs);
// the real host always has it via AddZbSecrets (registered unconditionally). Mirror that here.
services.AddSingleton<ISecretResolver>(new StubSecretResolver());
services.AddOtOpcUaDriverFactories();
using var sp = services.BuildServiceProvider();
@@ -54,6 +61,9 @@ public sealed class ResilienceInvokerFactoryRegistrationTests
{
var services = new ServiceCollection();
services.AddLogging();
// The driver-factory registration resolves ISecretResolver (Galaxy/OpcUaClient secret: refs);
// the real host always has it via AddZbSecrets (registered unconditionally). Mirror that here.
services.AddSingleton<ISecretResolver>(new StubSecretResolver());
services.AddOtOpcUaDriverFactories();
using var sp = services.BuildServiceProvider();
@@ -65,4 +75,12 @@ public sealed class ResilienceInvokerFactoryRegistrationTests
sp.GetRequiredService<DriverResiliencePipelineBuilder>()
.ShouldBeSameAs(sp.GetRequiredService<DriverResiliencePipelineBuilder>(), "builder must be a singleton");
}
// Minimal ISecretResolver so AddOtOpcUaDriverFactories' registration (which resolves it for
// Galaxy/OpcUaClient secret: refs) can be built. These tests exercise no secret: refs, so
// returning null for every name is sufficient — the real resolver comes from AddZbSecrets.
private sealed class StubSecretResolver : ISecretResolver
{
public Task<string?> GetAsync(SecretName name, CancellationToken ct) => Task.FromResult<string?>(null);
}
}