257 lines
7.8 KiB
C#
257 lines
7.8 KiB
C#
using adas_core.Application.Services.Caching;
|
|
using adas_core.Application.Services.Interfaces;
|
|
using adas_core.Domain.Enums;
|
|
using adas_core.Domain.Models.AppSettings;
|
|
using adas_core.Domain.Models.GroupedObservations;
|
|
using adas_core.Domain.Utils;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
using MongoDB.Bson;
|
|
using Moq;
|
|
|
|
namespace adas_core.Test.Services;
|
|
|
|
|
|
|
|
|
|
public class FakeLockProvider : ILockProvider
|
|
{
|
|
public Task<bool> AcquireAsync(string key, TimeSpan timeout) => Task.FromResult(true);
|
|
public Task ReleaseAsync(string key) => Task.CompletedTask;
|
|
}
|
|
|
|
public class FakeLockManagerService : LockManagerService
|
|
{
|
|
public FakeLockManagerService() : base(
|
|
Mock.Of<ILogger<LockManagerService>>(),
|
|
new FakeLockProvider())
|
|
{
|
|
}
|
|
}
|
|
|
|
|
|
public class FakeRedisService : RedisService, ICacheService
|
|
{
|
|
public bool WasCalled { get; private set; }
|
|
public string? LastKey { get; private set; }
|
|
|
|
public FakeRedisService() : base(
|
|
Options.Create(new CacheSettings()),
|
|
Mock.Of<ILogger<RedisService>>(),
|
|
new FakeLockManagerService())
|
|
{
|
|
}
|
|
|
|
|
|
Task<T> ICacheService.GetOrSetObjectAsync<T>(
|
|
string key,
|
|
Func<Task<T>> factory,
|
|
TimeSpan? ttl,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
WasCalled = true;
|
|
LastKey = key;
|
|
return factory();
|
|
}
|
|
|
|
Task<T> ICacheService.GetOrSetObjectAsync<T>(
|
|
GroupedField groupedField,
|
|
ObjectId patientId,
|
|
Func<Task<T>> factory,
|
|
TimeSpan? ttl,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
WasCalled = true;
|
|
return factory();
|
|
}
|
|
}
|
|
|
|
|
|
public class FakeCacheService : CacheService, ICacheService
|
|
{
|
|
public bool WasCalled { get; private set; }
|
|
public string? LastKey { get; private set; }
|
|
|
|
public FakeCacheService() : base(new FakeLockManagerService())
|
|
{
|
|
}
|
|
|
|
Task<T> ICacheService.GetOrSetObjectAsync<T>(
|
|
string key,
|
|
Func<Task<T>> factory,
|
|
TimeSpan? ttl,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
WasCalled = true;
|
|
LastKey = key;
|
|
return factory();
|
|
}
|
|
|
|
Task<T> ICacheService.GetOrSetObjectAsync<T>(
|
|
GroupedField groupedField,
|
|
ObjectId patientId,
|
|
Func<Task<T>> factory,
|
|
TimeSpan? ttl,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
WasCalled = true;
|
|
return factory();
|
|
}
|
|
}
|
|
|
|
|
|
public class FakeNoCacheService : NoCacheService, ICacheService
|
|
{
|
|
public bool WasCalled { get; private set; }
|
|
public string? LastKey { get; private set; }
|
|
|
|
Task<T> ICacheService.GetOrSetObjectAsync<T>(
|
|
string key,
|
|
Func<Task<T>> factory,
|
|
TimeSpan? ttl,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
WasCalled = true;
|
|
LastKey = key;
|
|
return factory();
|
|
}
|
|
|
|
Task<T> ICacheService.GetOrSetObjectAsync<T>(
|
|
GroupedField groupedField,
|
|
ObjectId patientId,
|
|
Func<Task<T>> factory,
|
|
TimeSpan? ttl,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
WasCalled = true;
|
|
return factory();
|
|
}
|
|
}
|
|
|
|
|
|
[TestFixture]
|
|
public class CacheDispatcherTest
|
|
{
|
|
private FakeRedisService _redisServiceFake = null!;
|
|
private FakeCacheService _memoryServiceFake = null!;
|
|
private FakeNoCacheService _noopServiceFake = null!;
|
|
private CacheSettings _cacheSettings = null!;
|
|
private CacheDispatcher _cacheDispatcher = null!;
|
|
|
|
[SetUp]
|
|
public void SetUp()
|
|
{
|
|
_redisServiceFake = new FakeRedisService();
|
|
_memoryServiceFake = new FakeCacheService();
|
|
_noopServiceFake = new FakeNoCacheService();
|
|
|
|
_cacheSettings = new CacheSettings();
|
|
|
|
_cacheDispatcher = new CacheDispatcher(
|
|
_redisServiceFake,
|
|
_memoryServiceFake,
|
|
_noopServiceFake,
|
|
_cacheSettings);
|
|
}
|
|
|
|
#region TC-23
|
|
|
|
[Test]
|
|
public async Task GetOrSetObjectAsync_UsesRedisService_WhenPatientsModeIsRedis()
|
|
{
|
|
// Arrange
|
|
var key = "patients:latestObs:abc";
|
|
var expectedResult = new { Name = "TestPatient" };
|
|
Func<Task<object>> factory = () => Task.FromResult<object>(expectedResult);
|
|
|
|
_cacheSettings.Patients = CacheEnum.Mode.Redis;
|
|
|
|
// Act
|
|
var result = await _cacheDispatcher.GetOrSetObjectAsync<object>(key, factory);
|
|
|
|
// Assert
|
|
Assert.That(_redisServiceFake.WasCalled, Is.True, "RedisService debería haber sido invocado");
|
|
Assert.That(_redisServiceFake.LastKey, Is.EqualTo(key));
|
|
Assert.That(_memoryServiceFake.WasCalled, Is.False, "CacheService NO debería haber sido invocado");
|
|
Assert.That(_noopServiceFake.WasCalled, Is.False, "NoCacheService NO debería haber sido invocado");
|
|
}
|
|
#endregion
|
|
|
|
#region TC-24
|
|
[Test]
|
|
public async Task GetOrSetObjectAsync_UsesCacheService_WhenAppointmentsModeIsCache()
|
|
{
|
|
// Arrange
|
|
var key = "appointments:patient:id:20260224";
|
|
var expectedResult = new { Name = "TestAppointment" };
|
|
Func<Task<object>> factory = () => Task.FromResult<object>(expectedResult);
|
|
|
|
_cacheSettings.Appointments = CacheEnum.Mode.Cache;
|
|
|
|
// Act
|
|
var result = await _cacheDispatcher.GetOrSetObjectAsync<object>(key, factory);
|
|
|
|
// Assert
|
|
Assert.That(_memoryServiceFake.WasCalled, Is.True, "CacheService debería haber sido invocado");
|
|
Assert.That(_memoryServiceFake.LastKey, Is.EqualTo(key));
|
|
Assert.That(_redisServiceFake.WasCalled, Is.False, "RedisService NO debería haber sido invocado");
|
|
Assert.That(_noopServiceFake.WasCalled, Is.False, "NoCacheService NO debería haber sido invocado");
|
|
}
|
|
#endregion
|
|
|
|
#region TC-25
|
|
[Test]
|
|
public async Task GetOrSetObjectAsync_UsesNoCacheService_WhenPumpObservationsModeIsNone()
|
|
{
|
|
// Arrange
|
|
var key = "pumpObs:latest:abc:10";
|
|
var expectedResult = new { Name = "TestPump" };
|
|
Func<Task<object>> factory = () => Task.FromResult<object>(expectedResult);
|
|
|
|
_cacheSettings.PumpObservations = CacheEnum.Mode.None;
|
|
|
|
// Act
|
|
var result = await _cacheDispatcher.GetOrSetObjectAsync<object>(key, factory);
|
|
|
|
// Assert
|
|
Assert.That(_noopServiceFake.WasCalled, Is.True, "NoCacheService debería haber sido invocado");
|
|
Assert.That(_noopServiceFake.LastKey, Is.EqualTo(key));
|
|
Assert.That(_redisServiceFake.WasCalled, Is.False, "RedisService NO debería haber sido invocado");
|
|
Assert.That(_memoryServiceFake.WasCalled, Is.False, "CacheService NO debería haber sido invocado");
|
|
}
|
|
#endregion
|
|
|
|
#region TC-26
|
|
[Test]
|
|
public async Task GetOrSetObjectAsync_UsesCacheService_WhenKeyIsUnrecognized()
|
|
{
|
|
// Arrange
|
|
var key = "unknown:prefix:key";
|
|
var expectedResult = new { Name = "TestUnknown" };
|
|
Func<Task<object>> factory = () => Task.FromResult<object>(expectedResult);
|
|
|
|
// Act
|
|
var result = await _cacheDispatcher.GetOrSetObjectAsync<object>(key, factory);
|
|
|
|
// Assert - Unknown keys fallback to InMemory (Cache)
|
|
Assert.That(_memoryServiceFake.WasCalled, Is.True, "CacheService debería haber sido invocado como fallback");
|
|
Assert.That(_memoryServiceFake.LastKey, Is.EqualTo(key));
|
|
Assert.That(_redisServiceFake.WasCalled, Is.False, "RedisService NO debería haber sido invocado");
|
|
Assert.That(_noopServiceFake.WasCalled, Is.False, "NoCacheService NO debería haber sido invocado");
|
|
}
|
|
|
|
[Test]
|
|
public void Classify_ReturnsUnknown_ForUnrecognizedPrefix()
|
|
{
|
|
// Arrange
|
|
var key = "unknown:prefix:key";
|
|
|
|
// Act
|
|
var result = CacheKeyClassifier.Classify(key);
|
|
|
|
// Assert
|
|
Assert.That(result, Is.EqualTo(CacheEnum.EntityType.Unknown));
|
|
}
|
|
#endregion
|
|
}
|