test(secrets): register ISecretResolver in driver-factory resilience tests (Task 10 fix)
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:
+18
@@ -4,6 +4,7 @@ using Xunit;
|
|||||||
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
||||||
using ZB.MOM.WW.OtOpcUa.Core.Resilience;
|
using ZB.MOM.WW.OtOpcUa.Core.Resilience;
|
||||||
using ZB.MOM.WW.OtOpcUa.Host.Drivers;
|
using ZB.MOM.WW.OtOpcUa.Host.Drivers;
|
||||||
|
using ZB.MOM.WW.Secrets.Abstractions;
|
||||||
|
|
||||||
namespace ZB.MOM.WW.OtOpcUa.Host.IntegrationTests;
|
namespace ZB.MOM.WW.OtOpcUa.Host.IntegrationTests;
|
||||||
|
|
||||||
@@ -24,6 +25,9 @@ public sealed class ResilienceInvokerFactoryRegistrationTests
|
|||||||
{
|
{
|
||||||
var services = new ServiceCollection();
|
var services = new ServiceCollection();
|
||||||
services.AddLogging();
|
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();
|
services.AddOtOpcUaDriverFactories();
|
||||||
|
|
||||||
using var sp = services.BuildServiceProvider();
|
using var sp = services.BuildServiceProvider();
|
||||||
@@ -38,6 +42,9 @@ public sealed class ResilienceInvokerFactoryRegistrationTests
|
|||||||
{
|
{
|
||||||
var services = new ServiceCollection();
|
var services = new ServiceCollection();
|
||||||
services.AddLogging();
|
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();
|
services.AddOtOpcUaDriverFactories();
|
||||||
|
|
||||||
using var sp = services.BuildServiceProvider();
|
using var sp = services.BuildServiceProvider();
|
||||||
@@ -54,6 +61,9 @@ public sealed class ResilienceInvokerFactoryRegistrationTests
|
|||||||
{
|
{
|
||||||
var services = new ServiceCollection();
|
var services = new ServiceCollection();
|
||||||
services.AddLogging();
|
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();
|
services.AddOtOpcUaDriverFactories();
|
||||||
|
|
||||||
using var sp = services.BuildServiceProvider();
|
using var sp = services.BuildServiceProvider();
|
||||||
@@ -65,4 +75,12 @@ public sealed class ResilienceInvokerFactoryRegistrationTests
|
|||||||
sp.GetRequiredService<DriverResiliencePipelineBuilder>()
|
sp.GetRequiredService<DriverResiliencePipelineBuilder>()
|
||||||
.ShouldBeSameAs(sp.GetRequiredService<DriverResiliencePipelineBuilder>(), "builder must be a singleton");
|
.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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user