From 61b8701d0ea739368ff1ff4ab4e948c3b968dbdb Mon Sep 17 00:00:00 2001 From: Mike Merkulov Date: Thu, 8 Oct 2026 14:25:46 +0300 Subject: [PATCH] Fix watcher startup without reload-enabled providers (#78) --- .../VaultChangeWatcher.cs | 5 ++ .../VaultChangeWatcherTests.cs | 47 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 Tests/VaultSharp.Extensions.Configuration.Test/VaultChangeWatcherTests.cs diff --git a/Source/VaultSharp.Extensions.Configuration/VaultChangeWatcher.cs b/Source/VaultSharp.Extensions.Configuration/VaultChangeWatcher.cs index d6ab993..bd36f2e 100644 --- a/Source/VaultSharp.Extensions.Configuration/VaultChangeWatcher.cs +++ b/Source/VaultSharp.Extensions.Configuration/VaultChangeWatcher.cs @@ -39,6 +39,11 @@ public VaultChangeWatcher(IConfiguration configuration, ILogger? logger = null) /// protected override async Task ExecuteAsync(CancellationToken stoppingToken) { + if (!this._configProviders.Any()) + { + return; + } + var timers = new Dictionary(); // key - index of config provider, value - timer var minTime = int.MaxValue; var i = 0; diff --git a/Tests/VaultSharp.Extensions.Configuration.Test/VaultChangeWatcherTests.cs b/Tests/VaultSharp.Extensions.Configuration.Test/VaultChangeWatcherTests.cs new file mode 100644 index 0000000..c8af01e --- /dev/null +++ b/Tests/VaultSharp.Extensions.Configuration.Test/VaultChangeWatcherTests.cs @@ -0,0 +1,47 @@ +namespace VaultSharp.Extensions.Configuration.Test +{ + using System; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Extensions.Configuration; + using Moq; + using Xunit; + + public class VaultChangeWatcherTests + { + [Theory] + [InlineData(false)] + [InlineData(true)] + public async Task StartAsync_CompletesWithoutReloadEnabledProviders(bool includeDisabledProvider) + { + var providers = includeDisabledProvider + ? new IConfigurationProvider[] + { + new VaultConfigurationProvider( + new VaultConfigurationSource(new VaultOptions("http://localhost:8200", "root", reloadOnChange: false), "test"), + null), + } + : Array.Empty(); + var configuration = new Mock(); + configuration.SetupGet(root => root.Providers).Returns(providers); + + using var watcher = new VaultChangeWatcher(configuration.Object); + using var cancellation = new CancellationTokenSource(); + + // Run startup separately so a synchronous retry loop cannot hang the test runner. + var startup = Task.Run(() => watcher.StartAsync(cancellation.Token)); + try + { + await startup.WaitAsync(TimeSpan.FromSeconds(2)); + Assert.NotNull(watcher.ExecuteTask); + Assert.True(watcher.ExecuteTask.IsCompletedSuccessfully); + } + finally + { + cancellation.Cancel(); + await startup.WaitAsync(TimeSpan.FromSeconds(5)); + await watcher.StopAsync(CancellationToken.None); + } + } + } +}