using ZB.MOM.WW.ScadaBridge.Commons.Entities.ExternalSystems; namespace ZB.MOM.WW.ScadaBridge.ExternalSystemGateway.Tests; /// Tests for (review 2026-10-21 05/P2). public class ExternalDefinitionLookupCacheTests { private static ExternalSystemDefinition Sys() => new("S", "https://x", "none") { Id = 1 }; /// Verifies hits within the TTL skip the repository and expiry refetches. /// A task that represents the asynchronous operation. [Fact] public async Task Hit_WithinTtl_SkipsFetch_AndExpiryRefetches() { var time = new FakeTimeProvider(DateTimeOffset.UtcNow); var cache = new ExternalDefinitionLookupCache(TimeSpan.FromSeconds(5), time); var fetches = 0; Task Fetch() { fetches++; return Task.FromResult(Sys()); } await cache.GetSystemAsync("S", Fetch); await cache.GetSystemAsync("S", Fetch); Assert.Equal(1, fetches); time.Advance(TimeSpan.FromSeconds(6)); await cache.GetSystemAsync("S", Fetch); Assert.Equal(2, fetches); } /// Verifies misses are not cached and a zero TTL disables caching. /// A task that represents the asynchronous operation. [Fact] public async Task NotFound_IsNotCached_AndZeroTtlDisables() { var cache = new ExternalDefinitionLookupCache(TimeSpan.FromSeconds(5)); var fetches = 0; Task Miss() { fetches++; return Task.FromResult(null); } await cache.GetSystemAsync("S", Miss); await cache.GetSystemAsync("S", Miss); Assert.Equal(2, fetches); var off = new ExternalDefinitionLookupCache(TimeSpan.Zero); fetches = 0; Task Hit() { fetches++; return Task.FromResult(Sys()); } await off.GetSystemAsync("S", Hit); await off.GetSystemAsync("S", Hit); Assert.Equal(2, fetches); } private sealed class FakeTimeProvider(DateTimeOffset start) : TimeProvider { private DateTimeOffset _now = start; public override DateTimeOffset GetUtcNow() => _now; public void Advance(TimeSpan by) => _now += by; } }