Files
ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway.Tests/ExternalDefinitionLookupCacheTests.cs
T

56 lines
2.3 KiB
C#

using ZB.MOM.WW.ScadaBridge.Commons.Entities.ExternalSystems;
namespace ZB.MOM.WW.ScadaBridge.ExternalSystemGateway.Tests;
/// <summary>Tests for <see cref="ExternalDefinitionLookupCache"/> (review 2026-10-21 05/P2).</summary>
public class ExternalDefinitionLookupCacheTests
{
private static ExternalSystemDefinition Sys() => new("S", "https://x", "none") { Id = 1 };
/// <summary>Verifies hits within the TTL skip the repository and expiry refetches.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[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<ExternalSystemDefinition?> Fetch() { fetches++; return Task.FromResult<ExternalSystemDefinition?>(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);
}
/// <summary>Verifies misses are not cached and a zero TTL disables caching.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task NotFound_IsNotCached_AndZeroTtlDisables()
{
var cache = new ExternalDefinitionLookupCache(TimeSpan.FromSeconds(5));
var fetches = 0;
Task<ExternalSystemDefinition?> Miss() { fetches++; return Task.FromResult<ExternalSystemDefinition?>(null); }
await cache.GetSystemAsync("S", Miss);
await cache.GetSystemAsync("S", Miss);
Assert.Equal(2, fetches);
var off = new ExternalDefinitionLookupCache(TimeSpan.Zero);
fetches = 0;
Task<ExternalSystemDefinition?> Hit() { fetches++; return Task.FromResult<ExternalSystemDefinition?>(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;
}
}