Conflicto de fusión en adas-core.LdapLogin/LdapLoginService.cs
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -4,35 +4,70 @@ using Serilog.Events;
|
||||
|
||||
namespace adas_core.Test.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a fake implementation of the ILogger interface, typically used as a test double to simulate logging behavior.
|
||||
/// </summary>
|
||||
public class FakeLogger : ILogger
|
||||
{
|
||||
public List<string> Messages { get; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Creates a logger context enriched with the specified <see cref="ILogEventEnricher"/> instances. In this implementation, the enrichers are not applied and the current <see cref="ILogger"/> instance is returned unchanged.
|
||||
/// </summary>
|
||||
/// <param name="enrichers">The collection of enrichers intended to add contextual properties to log events.</param>
|
||||
/// <returns>The current <see cref="ILogger"/> instance, without the supplied enrichers applied.</returns>
|
||||
public ILogger ForContext(IEnumerable<ILogEventEnricher> enrichers)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a logger context enriched with the specified property and value, returning the same logger instance.
|
||||
/// </summary>
|
||||
/// <param name="propertyName">The name of the property to add to the logger context.</param>
|
||||
/// <param name="value">The value associated with the property. Can be null.</param>
|
||||
/// <param name="destructureObjects">Indicates whether complex objects should be destructured. Defaults to false.</param>
|
||||
/// <returns>The current <see cref="ILogger"/> instance.</returns>
|
||||
public ILogger ForContext(string propertyName, object? value, bool destructureObjects = false)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a logger context associated with the specified source type by returning the current <see cref="ILogger"/> instance.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type used to enrich the logger context.</typeparam>
|
||||
/// <returns>The current <see cref="ILogger"/> instance.</returns>
|
||||
public ILogger ForContext<TSource>()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current logger instance, ignoring the provided source type. Provides a no-op context enrichment for log messages.
|
||||
/// </summary>
|
||||
/// <param name="source">The source type used to enrich the logger context.</param>
|
||||
/// <returns>The current <see cref="ILogger"/> instance.</returns>
|
||||
public ILogger ForContext(Type source)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends the rendered message of the provided log event to the internal messages collection.
|
||||
/// </summary>
|
||||
/// <param name="logEvent">The log event whose rendered message will be added to the collection.</param>
|
||||
public void Write(LogEvent logEvent)
|
||||
{
|
||||
Messages.Add(logEvent.RenderMessage());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a log message at the specified level to the internal messages collection, formatting it with the provided property values.
|
||||
/// </summary>
|
||||
/// <param name="level">The severity level of the log event.</param>
|
||||
/// <param name="messageTemplate">The message template containing placeholders for the property values.</param>
|
||||
/// <param name="propertyValues">An optional array of objects to format the message template. Can be <see langword="null"/>.</param>
|
||||
public void Write(LogEventLevel level, string messageTemplate, params object?[]? propertyValues)
|
||||
{
|
||||
// Manejar la situación donde propertyValues es nulo, si es necesario
|
||||
@@ -42,13 +77,30 @@ public class FakeLogger : ILogger
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Writes a log entry by formatting the provided message template with the given property value and adding it to the messages collection.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the property value to be substituted into the message template.</typeparam>
|
||||
/// <param name="level">The log event level associated with the entry being written.</param>
|
||||
/// <param name="messageTemplate">The message template containing a format placeholder for the property value.</param>
|
||||
/// <param name="propertyValue">The value to be inserted into the message template.</param>
|
||||
public void Write<T>(LogEventLevel level, string messageTemplate, T propertyValue)
|
||||
{
|
||||
Messages.Add(string.Format(messageTemplate, propertyValue));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Captures a log entry by appending the formatted message to the internal <c>Messages</c> collection.
|
||||
/// When <paramref name="propertyValues"/> is provided, the <paramref name="messageTemplate"/> is formatted with those values; otherwise the template is stored as-is.
|
||||
/// If <paramref name="exception"/> is not null, its message is appended as an additional entry.
|
||||
/// </summary>
|
||||
/// <param name="level">The severity level of the log event.</param>
|
||||
/// <param name="exception">An optional exception whose message is recorded when not null.</param>
|
||||
/// <param name="messageTemplate">The message template to log, used directly when <paramref name="propertyValues"/> is null.</param>
|
||||
/// <param name="propertyValues">Optional values to substitute into <paramref name="messageTemplate"/> via <c>string.Format</c>.</param>
|
||||
public void Write(LogEventLevel level, Exception? exception, string messageTemplate,
|
||||
params object?[]? propertyValues)
|
||||
params object?[]? propertyValues)
|
||||
{
|
||||
Messages.Add(propertyValues == null ? messageTemplate : string.Format(messageTemplate, propertyValues));
|
||||
|
||||
@@ -56,11 +108,23 @@ public class FakeLogger : ILogger
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether logging is enabled for the specified log event level. Currently returns <c>true</c> unconditionally, allowing all log levels to be processed.
|
||||
/// </summary>
|
||||
/// <param name="level">The log event level to evaluate.</param>
|
||||
/// <returns><c>true</c> if logging is enabled for the given level; otherwise, <c>false</c>.</returns>
|
||||
public bool IsEnabled(LogEventLevel level)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a log entry by formatting the provided message template with the supplied property value and appending it to the Messages collection. If an exception is supplied, its message is also appended to the collection.
|
||||
/// </summary>
|
||||
/// <param name="level">The severity level of the log event.</param>
|
||||
/// <param name="exception">An optional exception whose message, when not null, is added to the Messages collection after the formatted message.</param>
|
||||
/// <param name="messageTemplate">The message template string used to format the log entry.</param>
|
||||
/// <param name="propertyValue">The value to be substituted into the message template.</param>
|
||||
public void Write<T>(LogEventLevel level, Exception? exception, string messageTemplate, T propertyValue)
|
||||
{
|
||||
Messages.Add(string.Format(messageTemplate, propertyValue));
|
||||
|
||||
@@ -12,72 +12,78 @@ namespace adas_core.Test.Models.SignalR;
|
||||
[TestFixture]
|
||||
public class SubscriberGroupedTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes test fixtures used by grouped observation and WebSocket subscriber tests, including
|
||||
/// <see cref="GroupedObservation"/>, <see cref="GroupedField"/>, <see cref="WsSubscriber"/>, and
|
||||
/// <see cref="WsSubscriberGrouped"/> instances configured for two distinct patients with shift- and
|
||||
/// hour-based regularities and last/last-filled result mappings.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
// Set up GroupedObservation
|
||||
_go = new GroupedObservation
|
||||
public void Setup()
|
||||
{
|
||||
PatientId = _patient1,
|
||||
Name = "GroupedObservationTest1",
|
||||
Group = "GroupedObservationTest1",
|
||||
Observations = []
|
||||
};
|
||||
_go2 = new GroupedObservation
|
||||
{
|
||||
PatientId = _patient2,
|
||||
Name = "GroupedObservationTest2",
|
||||
Group = "GroupedObservationTest2",
|
||||
Observations = []
|
||||
};
|
||||
|
||||
// Set up GroupedField
|
||||
_gf1 = new GroupedField
|
||||
{
|
||||
Name = "GroupedObservationTest1",
|
||||
Group = "GroupedFieldTest1",
|
||||
StartTimeShift = ["00:59", "04:59", "08:59", "12:59", "16:59", "20:59"],
|
||||
Max = 24,
|
||||
Regularity = GroupedObservationEnum.Regularity.Shift,
|
||||
Result = [GroupedObservationEnum.Result.Last]
|
||||
};
|
||||
_gf2 = new GroupedField
|
||||
{
|
||||
Names = ["GroupedObservationTest2", "GroupedObservationTest1"],
|
||||
Group = "GroupedFieldTest2",
|
||||
Max = 24,
|
||||
Regularity = GroupedObservationEnum.Regularity.Hour,
|
||||
Result = [GroupedObservationEnum.Result.Last, GroupedObservationEnum.Result.LastFilled]
|
||||
};
|
||||
|
||||
// Set up WebSocketSubscriber
|
||||
_ws1 = new WsSubscriber("1234")
|
||||
{
|
||||
Id = "1234",
|
||||
Box = "Box1",
|
||||
Section = "Section1",
|
||||
Version = "1.0.0",
|
||||
GroupedFields = [],
|
||||
SubscriptionType = SubscriptionEnum.WsType.Box
|
||||
};
|
||||
_ws2 = new WsSubscriber("1234")
|
||||
{
|
||||
Id = "5321",
|
||||
Box = "Box2",
|
||||
Section = "Section1",
|
||||
Version = "1.0.0",
|
||||
GroupedFields = [],
|
||||
SubscriptionType = SubscriptionEnum.WsType.Box
|
||||
};
|
||||
|
||||
// Set up groupedFields for subscribers
|
||||
_ws1.GroupedFields = [_gf1];
|
||||
_ws2.GroupedFields = [_gf1, _gf2];
|
||||
|
||||
// Set up WsSubscriberGrouped
|
||||
_wsBase = new WsSubscriberGrouped(_patient1, _ws1.Id, "Romance Standard Time", _gf1, _go, delegate { });
|
||||
_wsBase2 = new WsSubscriberGrouped(_patient2, _ws2.Id, "Romance Standard Time", _gf2, _go2, delegate { });
|
||||
}
|
||||
// Set up GroupedObservation
|
||||
_go = new GroupedObservation
|
||||
{
|
||||
PatientId = _patient1,
|
||||
Name = "GroupedObservationTest1",
|
||||
Group = "GroupedObservationTest1",
|
||||
Observations = []
|
||||
};
|
||||
_go2 = new GroupedObservation
|
||||
{
|
||||
PatientId = _patient2,
|
||||
Name = "GroupedObservationTest2",
|
||||
Group = "GroupedObservationTest2",
|
||||
Observations = []
|
||||
};
|
||||
|
||||
// Set up GroupedField
|
||||
_gf1 = new GroupedField
|
||||
{
|
||||
Name = "GroupedObservationTest1",
|
||||
Group = "GroupedFieldTest1",
|
||||
StartTimeShift = ["00:59", "04:59", "08:59", "12:59", "16:59", "20:59"],
|
||||
Max = 24,
|
||||
Regularity = GroupedObservationEnum.Regularity.Shift,
|
||||
Result = [GroupedObservationEnum.Result.Last]
|
||||
};
|
||||
_gf2 = new GroupedField
|
||||
{
|
||||
Names = ["GroupedObservationTest2", "GroupedObservationTest1"],
|
||||
Group = "GroupedFieldTest2",
|
||||
Max = 24,
|
||||
Regularity = GroupedObservationEnum.Regularity.Hour,
|
||||
Result = [GroupedObservationEnum.Result.Last, GroupedObservationEnum.Result.LastFilled]
|
||||
};
|
||||
|
||||
// Set up WebSocketSubscriber
|
||||
_ws1 = new WsSubscriber("1234")
|
||||
{
|
||||
Id = "1234",
|
||||
Box = "Box1",
|
||||
Section = "Section1",
|
||||
Version = "1.0.0",
|
||||
GroupedFields = [],
|
||||
SubscriptionType = SubscriptionEnum.WsType.Box
|
||||
};
|
||||
_ws2 = new WsSubscriber("1234")
|
||||
{
|
||||
Id = "5321",
|
||||
Box = "Box2",
|
||||
Section = "Section1",
|
||||
Version = "1.0.0",
|
||||
GroupedFields = [],
|
||||
SubscriptionType = SubscriptionEnum.WsType.Box
|
||||
};
|
||||
|
||||
// Set up groupedFields for subscribers
|
||||
_ws1.GroupedFields = [_gf1];
|
||||
_ws2.GroupedFields = [_gf1, _gf2];
|
||||
|
||||
// Set up WsSubscriberGrouped
|
||||
_wsBase = new WsSubscriberGrouped(_patient1, _ws1.Id, "Romance Standard Time", _gf1, _go, delegate { });
|
||||
_wsBase2 = new WsSubscriberGrouped(_patient2, _ws2.Id, "Romance Standard Time", _gf2, _go2, delegate { });
|
||||
}
|
||||
|
||||
private GroupedObservation _go;
|
||||
private GroupedObservation _go2;
|
||||
@@ -94,145 +100,161 @@ public class SubscriberGroupedTest
|
||||
private readonly ObjectId _patient1 = ObjectId.GenerateNewId();
|
||||
private readonly ObjectId _patient2 = ObjectId.GenerateNewId();
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the <see cref="ISubscriberGroupedService.GetGrouped"/> method returns the list of grouped subscribers provided by the mocked service.
|
||||
/// Ensures the service correctly returns the expected collection of <see cref="WsSubscriberGrouped"/> items without modification.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void GetGroupeds_ReturnsExpectedResult()
|
||||
{
|
||||
var mockSubscriberGrouped = new List<WsSubscriberGrouped>
|
||||
public void GetGroupeds_ReturnsExpectedResult()
|
||||
{
|
||||
new(_patient1, _ws1.Id, "Romance Standard Time", _gf1, _go, delegate { }),
|
||||
new(_patient2, _ws1.Id, "Romance Standard Time", _gf1, _go, delegate { })
|
||||
};
|
||||
|
||||
var mockSubscriberGroupedService = new Mock<ISubscriberGroupedService>();
|
||||
mockSubscriberGroupedService.Setup(x => x.GetGrouped()).Returns(mockSubscriberGrouped);
|
||||
|
||||
|
||||
var result = mockSubscriberGroupedService.Object.GetGrouped();
|
||||
|
||||
Assert.That(result, Is.EqualTo(mockSubscriberGrouped));
|
||||
}
|
||||
var mockSubscriberGrouped = new List<WsSubscriberGrouped>
|
||||
{
|
||||
new(_patient1, _ws1.Id, "Romance Standard Time", _gf1, _go, delegate { }),
|
||||
new(_patient2, _ws1.Id, "Romance Standard Time", _gf1, _go, delegate { })
|
||||
};
|
||||
|
||||
var mockSubscriberGroupedService = new Mock<ISubscriberGroupedService>();
|
||||
mockSubscriberGroupedService.Setup(x => x.GetGrouped()).Returns(mockSubscriberGrouped);
|
||||
|
||||
|
||||
var result = mockSubscriberGroupedService.Object.GetGrouped();
|
||||
|
||||
Assert.That(result, Is.EqualTo(mockSubscriberGrouped));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the behavior of the <c>Compare</c> extension method by asserting that it returns <c>true</c> when the gender and patient identifiers match the active context, and <c>false</c> when they do not, covering both the primary and secondary contexts.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Compare_ExtensionResult()
|
||||
{
|
||||
using (Assert.EnterMultipleScope())
|
||||
public void Compare_ExtensionResult()
|
||||
{
|
||||
Assert.That(_wsBase.Compare(_gf1, _go.PatientId), Is.True);
|
||||
Assert.That(_wsBase.Compare(_gf1, _go2.PatientId), Is.False);
|
||||
Assert.That(_wsBase.Compare(_gf2, _go.PatientId), Is.False);
|
||||
Assert.That(_wsBase2.Compare(_gf2, _go2.PatientId), Is.True);
|
||||
};
|
||||
}
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(_wsBase.Compare(_gf1, _go.PatientId), Is.True);
|
||||
Assert.That(_wsBase.Compare(_gf1, _go2.PatientId), Is.False);
|
||||
Assert.That(_wsBase.Compare(_gf2, _go.PatientId), Is.False);
|
||||
Assert.That(_wsBase2.Compare(_gf2, _go2.PatientId), Is.True);
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that a new patient observation is considered relevant for its group when it is the first observation recorded within the current hour.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Observation_is_rrelevant_because_is_the_first_in_hour()
|
||||
{
|
||||
var obs = new PatientObservation
|
||||
public void Observation_is_rrelevant_because_is_the_first_in_hour()
|
||||
{
|
||||
Time = DateTime.UtcNow,
|
||||
Value = 5
|
||||
};
|
||||
|
||||
|
||||
Assert.That(_wsBase.IsNewObservationRelevantForGroup(obs), Is.True);
|
||||
}
|
||||
var obs = new PatientObservation
|
||||
{
|
||||
Time = DateTime.UtcNow,
|
||||
Value = 5
|
||||
};
|
||||
|
||||
|
||||
Assert.That(_wsBase.IsNewObservationRelevantForGroup(obs), Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that a new patient observation is considered relevant for a grouped observation when an observation already exists within the configured hour interval and the grouping uses the Max result.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Grouped_Observation_Already_Observations_In_Hour_Should_Be_Relevant_By_Max_Result()
|
||||
{
|
||||
var patientId = ObjectId.GenerateNewId();
|
||||
var grouped = new GroupedObservation
|
||||
public void Grouped_Observation_Already_Observations_In_Hour_Should_Be_Relevant_By_Max_Result()
|
||||
{
|
||||
PatientId = patientId,
|
||||
Name = "GroupedObservationTest1",
|
||||
Group = "GroupedObservationTest1",
|
||||
Observations =
|
||||
[
|
||||
new GroupedObservationObs
|
||||
{
|
||||
Max = new GroupedObservationObsValue(5, DateTime.UtcNow)
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var wsSubscriber = new WsSubscriber("1234")
|
||||
{
|
||||
Id = "1234",
|
||||
Box = "Box1",
|
||||
Section = "Section1",
|
||||
Version = "1.0.0",
|
||||
GroupedFields = [],
|
||||
SubscriptionType = SubscriptionEnum.WsType.Box
|
||||
};
|
||||
|
||||
var groupedField = new GroupedField
|
||||
{
|
||||
Names = ["GroupedObservationTest2", "GroupedObservationTest1"],
|
||||
Group = "GroupedFieldTest2",
|
||||
Max = 24,
|
||||
Regularity = GroupedObservationEnum.Regularity.Hour,
|
||||
Result = [GroupedObservationEnum.Result.Max]
|
||||
};
|
||||
|
||||
var newObservation = new PatientObservation
|
||||
{
|
||||
PatientId = patientId,
|
||||
Time = DateTime.UtcNow,
|
||||
Value = 8
|
||||
};
|
||||
|
||||
var wsGrouped = new WsSubscriberGrouped(patientId, wsSubscriber.Id, "", groupedField, grouped, delegate { });
|
||||
//for utc.now two observations, last was 5 and now is 8 result is by Max, should be relevant
|
||||
Assert.That(wsGrouped.IsNewObservationRelevantForGroup(newObservation), Is.True);
|
||||
}
|
||||
var patientId = ObjectId.GenerateNewId();
|
||||
var grouped = new GroupedObservation
|
||||
{
|
||||
PatientId = patientId,
|
||||
Name = "GroupedObservationTest1",
|
||||
Group = "GroupedObservationTest1",
|
||||
Observations =
|
||||
[
|
||||
new GroupedObservationObs
|
||||
{
|
||||
Max = new GroupedObservationObsValue(5, DateTime.UtcNow)
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var wsSubscriber = new WsSubscriber("1234")
|
||||
{
|
||||
Id = "1234",
|
||||
Box = "Box1",
|
||||
Section = "Section1",
|
||||
Version = "1.0.0",
|
||||
GroupedFields = [],
|
||||
SubscriptionType = SubscriptionEnum.WsType.Box
|
||||
};
|
||||
|
||||
var groupedField = new GroupedField
|
||||
{
|
||||
Names = ["GroupedObservationTest2", "GroupedObservationTest1"],
|
||||
Group = "GroupedFieldTest2",
|
||||
Max = 24,
|
||||
Regularity = GroupedObservationEnum.Regularity.Hour,
|
||||
Result = [GroupedObservationEnum.Result.Max]
|
||||
};
|
||||
|
||||
var newObservation = new PatientObservation
|
||||
{
|
||||
PatientId = patientId,
|
||||
Time = DateTime.UtcNow,
|
||||
Value = 8
|
||||
};
|
||||
|
||||
var wsGrouped = new WsSubscriberGrouped(patientId, wsSubscriber.Id, "", groupedField, grouped, delegate { });
|
||||
//for utc.now two observations, last was 5 and now is 8 result is by Max, should be relevant
|
||||
Assert.That(wsGrouped.IsNewObservationRelevantForGroup(newObservation), Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that a new observation is considered not relevant for a grouped observation when the grouping rule is set to "Max", the regularity is "Hour", an observation already exists within the same hour, and the new observation's value does not exceed the existing maximum value.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Grouped_Observation_Already_Observations_In_Hour_Should_Be_IRelevant_By_Max_Result()
|
||||
{
|
||||
var patientId = ObjectId.GenerateNewId();
|
||||
var grouped = new GroupedObservation
|
||||
public void Grouped_Observation_Already_Observations_In_Hour_Should_Be_IRelevant_By_Max_Result()
|
||||
{
|
||||
PatientId = patientId,
|
||||
Name = "GroupedObservationTest1",
|
||||
Group = "GroupedObservationTest1",
|
||||
Observations =
|
||||
[
|
||||
new GroupedObservationObs
|
||||
{
|
||||
Max = new GroupedObservationObsValue(5, DateTime.UtcNow),
|
||||
Time = DateTime.UtcNow
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var wsSubscriber = new WsSubscriber("1234")
|
||||
{
|
||||
Id = "1234",
|
||||
Box = "Box1",
|
||||
Section = "Section1",
|
||||
Version = "1.0.0",
|
||||
GroupedFields = [],
|
||||
SubscriptionType = SubscriptionEnum.WsType.Box
|
||||
};
|
||||
|
||||
var groupedField = new GroupedField
|
||||
{
|
||||
Names = ["GroupedObservationTest2", "GroupedObservationTest1"],
|
||||
Group = "GroupedFieldTest2",
|
||||
Max = 24,
|
||||
Regularity = GroupedObservationEnum.Regularity.Hour,
|
||||
Result = [GroupedObservationEnum.Result.Max]
|
||||
};
|
||||
|
||||
var newObservation = new PatientObservation
|
||||
{
|
||||
PatientId = patientId,
|
||||
Time = DateTime.UtcNow,
|
||||
Value = 4
|
||||
};
|
||||
|
||||
var wsGrouped = new WsSubscriberGrouped(patientId, wsSubscriber.Id, "", groupedField, grouped, delegate { });
|
||||
//for utc.now two observations, last was 5 and now is 4 result is by Max, should be Irelevant
|
||||
Assert.That(wsGrouped.IsNewObservationRelevantForGroup(newObservation), Is.False);
|
||||
}
|
||||
var patientId = ObjectId.GenerateNewId();
|
||||
var grouped = new GroupedObservation
|
||||
{
|
||||
PatientId = patientId,
|
||||
Name = "GroupedObservationTest1",
|
||||
Group = "GroupedObservationTest1",
|
||||
Observations =
|
||||
[
|
||||
new GroupedObservationObs
|
||||
{
|
||||
Max = new GroupedObservationObsValue(5, DateTime.UtcNow),
|
||||
Time = DateTime.UtcNow
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var wsSubscriber = new WsSubscriber("1234")
|
||||
{
|
||||
Id = "1234",
|
||||
Box = "Box1",
|
||||
Section = "Section1",
|
||||
Version = "1.0.0",
|
||||
GroupedFields = [],
|
||||
SubscriptionType = SubscriptionEnum.WsType.Box
|
||||
};
|
||||
|
||||
var groupedField = new GroupedField
|
||||
{
|
||||
Names = ["GroupedObservationTest2", "GroupedObservationTest1"],
|
||||
Group = "GroupedFieldTest2",
|
||||
Max = 24,
|
||||
Regularity = GroupedObservationEnum.Regularity.Hour,
|
||||
Result = [GroupedObservationEnum.Result.Max]
|
||||
};
|
||||
|
||||
var newObservation = new PatientObservation
|
||||
{
|
||||
PatientId = patientId,
|
||||
Time = DateTime.UtcNow,
|
||||
Value = 4
|
||||
};
|
||||
|
||||
var wsGrouped = new WsSubscriberGrouped(patientId, wsSubscriber.Id, "", groupedField, grouped, delegate { });
|
||||
//for utc.now two observations, last was 5 and now is 4 result is by Max, should be Irelevant
|
||||
Assert.That(wsGrouped.IsNewObservationRelevantForGroup(newObservation), Is.False);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,296 @@
|
||||
# adas-core.Test — Automated Test Suite
|
||||
|
||||
> The **integration and unit test project** for the ADAS Core platform.
|
||||
> Provides comprehensive automated coverage across repositories, services, domain logic, and module-level behavior. Tests run against an in-process MongoDB instance (Mongo2Go), an in-memory distributed-lock provider, and mocked external dependencies.
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Overview](#overview)
|
||||
2. [Responsibilities](#responsibilities)
|
||||
3. [Project Structure](#project-structure)
|
||||
4. [Dependencies](#dependencies)
|
||||
5. [Test Architecture](#test-architecture)
|
||||
6. [Test Data & Builders](#test-data--builders)
|
||||
7. [Running the Tests](#running-the-tests)
|
||||
8. [Design Rules](#design-rules)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
`adas-core.Test` is a dedicated .NET 8 test assembly that exercises the ADAS Core platform end-to-end, from domain-level calculations to repository CRUD and service orchestration. It follows a **layered test pyramid**: fast unit tests for pure logic, integration tests backed by Mongo2Go for persistence, and module-level tests for device abstractions.
|
||||
|
||||
Key characteristics:
|
||||
|
||||
- **NUnit + Moq** — Primary test framework and mocking library.
|
||||
- **Mongo2Go Integration** — `IntegrationDb` spins up a real MongoDB instance in RAM for repository and migration tests, then tears it down cleanly.
|
||||
- **In-Memory Locking** — `InMemoryLockProvider` enables `CacheService` and `LockManagerService` tests without Redis.
|
||||
- **Shared Test Data** — `TestUtilities` provides factory methods for domain entities (`Patient`, `Admission`, `PointOfCare`, etc.) ensuring consistent, valid test fixtures.
|
||||
- **Fake Logger** — `FakeLogger` implements `ILogger` to capture and assert on log output during service tests.
|
||||
- **Customization Tests** — Hospital-specific calculated-observation logic is validated under `Customizations/`.
|
||||
- **Fakes Framework** — `Microsoft.QualityTools.Testing.Fakes` supports shim-based isolation for static or sealed dependencies.
|
||||
|
||||
---
|
||||
|
||||
## Responsibilities
|
||||
|
||||
| Concern | What this project does |
|
||||
|---------|----------------------|
|
||||
| **Unit Tests — Domain** | Pure logic tests for domain entities, value objects, enums, and utility classes that have no external dependencies. |
|
||||
| **Unit Tests — Services** | Isolated service tests using Moq for all collaborators (repositories, messaging, logging). |
|
||||
| **Integration Tests — Repositories** | CRUD, filtering, pagination, and aggregation tests against a live Mongo2Go database via `IntegrationDb`. |
|
||||
| **Integration Tests — Migrations** | MongoMigrations.Core-based schema-migration tests (`MongodbMigrationTest`). |
|
||||
| **Module Tests** | Tests for `LightBeaconService`, `RelayService`, and cache/provider implementations using in-memory substitutes. |
|
||||
| **Customisation Tests** | Hospital-specific calculated-observation formulas validated per deployment (H12O, HPAZ, HRYC, HUVH). |
|
||||
| **Test Fixture Bootstrapping** | `IntegrationDb` handles one-time MongoDB startup/teardown for the entire integration test suite. |
|
||||
| **Shared Factories** | `TestUtilities` generates consistently valid domain objects with deterministic `ObjectId` values. |
|
||||
| **Logging Assertions** | `FakeLogger` collects log messages so tests can verify warning/error emission paths. |
|
||||
| **Coverage** | `coverlet.collector` instruments the assembly during CI to produce code-coverage reports. |
|
||||
|
||||
---
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
adas-core.Test/
|
||||
├── Customizations/
|
||||
│ ├── H12O/UCIN/CalculatedObservationsTest.cs # H12O hospital computed-observation formulas
|
||||
│ ├── HPAZ/CalculatedObservationsTest.cs # HPAZ hospital computed-observation formulas
|
||||
│ ├── HRYC/CalculatedObservationsTest.cs # HRYC hospital computed-observation formulas
|
||||
│ ├── HUVH/UCIA/CalculatedObservationsTest.cs # HUVH-UCIA computed-observation formulas
|
||||
│ └── HUVH/UCIN/CalculatedObservationsTest.cs # HUVH-UCIN computed-observation formulas
|
||||
│
|
||||
├── Models/
|
||||
│ ├── FakeLogger.cs # Serilog ILogger test double (captures log output)
|
||||
│ └── SignalR/SubscriberGroupedTest.cs # SignalR subscription grouping tests
|
||||
│
|
||||
├── Repositories/
|
||||
│ ├── IntegrationDb.cs # One-time Mongo2Go runner setup/tear-down fixture
|
||||
│ ├── MongodbMigrationTest.cs # MongoMigrations.Core migration validation
|
||||
│ ├── AdmissionRepositoryTest.cs # Admission aggregate CRUD tests
|
||||
│ ├── AlarmRepositoryTest.cs # Alarm entity CRUD tests
|
||||
│ ├── AppointmentRepositoryTest.cs # Appointment CRUD and archive tests
|
||||
│ ├── ConfigObservationRepositoryTest.cs # Observation config CRUD tests
|
||||
│ ├── ConfigPumpsRepositoryTest.cs # Pump config CRUD tests
|
||||
│ ├── ConfigUnitsRepositoryTest.cs # Unit config CRUD tests
|
||||
│ ├── DiagnosisRepositoryTest.cs # Diagnosis CRUD and archive tests
|
||||
│ ├── DisplayConfigTest.cs # Display configuration tests
|
||||
│ ├── HistoricalConfigChangesRepositoryTest.cs # Historical config audit tests
|
||||
│ ├── MasterListRepositoryTest.cs # Master-list CRUD tests
|
||||
│ ├── MedicineRepositoryTest.cs # Medicine entity tests
|
||||
│ ├── ObservationRepositoryTest.cs # Observation CRUD and archive tests
|
||||
│ ├── PatientRepositoryTest.cs # Patient aggregate tests
|
||||
│ ├── PointOfCareRepositoryTests.cs # PoC repository tests
|
||||
│ ├── PoCMappingRepositoryTest.cs # PoC-mapping tests
|
||||
│ ├── PoCSettingsRepositoryTest.cs # PoC-settings tests
|
||||
│ ├── Pump*RepositoryTest.cs # Pump state/alarm/event/archive tests
|
||||
│ ├── RecordingAlertRepositoryTest.cs # Recording alert CRUD and archive tests
|
||||
│ ├── SectionRepositoryTest.cs # Section/ward tests
|
||||
│ ├── ServiceConfigRepositoryTest.cs # Service-config tests
|
||||
│ ├── TreatmentRepositoryTest.cs # Treatment CRUD and archive tests
|
||||
│ └── UnitRepositoryTest.cs # Unit aggregate tests
|
||||
│
|
||||
├── Services/
|
||||
│ ├── AdmissionServiceTest.cs # Admission orchestration tests
|
||||
│ ├── AlarmServiceTest.cs # Alarm service logic tests
|
||||
│ ├── CacheDispatcherTest.cs # Cache dispatcher routing tests
|
||||
│ ├── CacheServiceTest.cs # Cache hit/miss/eviction/concurrency tests
|
||||
│ ├── CameraServiceTest.cs # Camera service tests
|
||||
│ ├── ConfigObservationServiceTest.cs # Observation config service tests
|
||||
│ ├── ConfigPumpsServiceTest.cs # Pump config service tests
|
||||
│ ├── ConfigUnitsServiceTest.cs # Unit config service tests
|
||||
│ ├── DiagnosisServiceTest.cs # Diagnosis orchestration tests
|
||||
│ ├── DischargeServiceTest.cs # Discharge workflow tests
|
||||
│ ├── DisplayServiceTest.cs # Display configuration service tests
|
||||
│ ├── GroupedObservationServiceTest.cs # Grouped observation calculation tests
|
||||
│ ├── HistoricalConfigChangesServiceTest.cs # Historical config changes service tests
|
||||
│ ├── InMemoryLockProviderTest.cs # In-memory distributed-lock tests
|
||||
│ ├── LightBeaconServiceTest.cs # Light beacon module tests
|
||||
│ ├── MasterListServiceTest.cs # Master-list service tests
|
||||
│ ├── MedicineServiceTest.cs # Medicine service tests
|
||||
│ ├── NoCacheServiceTest.cs # No-cache fallback tests
|
||||
│ ├── ObservationServiceTest.cs # Observation orchestration tests
|
||||
│ ├── PatientServiceTest.cs # Patient orchestration tests
|
||||
│ ├── PointOfCareServiceTest.cs # PoC service tests
|
||||
│ ├── PublisherServiceTest.cs # Event-publisher service tests
|
||||
│ ├── PumpServiceTest.cs # Pump orchestration tests
|
||||
│ ├── RecordingAlertServiceTest.cs # Recording alert service tests
|
||||
│ ├── RecordingServiceTest.cs # Recording service tests
|
||||
│ ├── RedisLockProviderTest.cs # Redis-backed lock-provider tests
|
||||
│ ├── RedisServiceTest.cs # Redis caching service tests
|
||||
│ ├── RelayServiceTest.cs # Relay module tests
|
||||
│ ├── SchedulerServiceTest.cs # Background scheduler tests
|
||||
│ ├── SendAlertServiceTest.cs # Alert-dispatch service tests
|
||||
│ ├── ServiceConfigServiceTest.cs # Service-config orchestration tests
|
||||
│ ├── TreatmentServiceTest.cs # Treatment orchestration tests
|
||||
│ └── UnitServiceTest.cs # Unit orchestration tests
|
||||
│
|
||||
├── Utilities/
|
||||
│ ├── CacheKeyClassifierTest.cs # Cache-key parsing and classification tests
|
||||
│ └── TestUtilities.cs # Shared entity builders and helper methods
|
||||
│
|
||||
└── Usings.cs # Global `using NUnit.Framework`
|
||||
```
|
||||
|
||||
| Folder | Role |
|
||||
|--------|------|
|
||||
| `Customizations/` | Hospital-specific test fixtures isolating per-client business rules. Each subfolder mirrors a real deployment configuration. |
|
||||
| `Models/` | Shared test doubles (`FakeLogger`) and SignalR model tests. |
|
||||
| `Repositories/` | Integration tests for every concrete `MongoRepository` subclass. `IntegrationDb` bootstraps the ephemeral MongoDB instance. |
|
||||
| `Services/` | Unit and integration tests for Application-layer service implementations (caching, alerting, pumping, relays, beacons, etc.). |
|
||||
| `Utilities/` | Helper factories for test data (`TestUtilities`) and utility-class tests (`CacheKeyClassifierTest`). |
|
||||
|
||||
---
|
||||
|
||||
## Dependencies
|
||||
|
||||
### Downstream References
|
||||
|
||||
| Project | Role |
|
||||
|---------|------|
|
||||
| `adas-core.Domain` | Domain entities, enums, and exceptions exercised by unit tests. |
|
||||
| `adas-core.Infrastructure` | Concrete repositories, services, and DB context exercised by integration tests. |
|
||||
| `adas-core` (Host) | WebHost builder, middleware pipeline, and DI configuration tested via integration fixtures. |
|
||||
|
||||
### NuGet Packages
|
||||
|
||||
| Package | Version | Purpose |
|
||||
|---------|---------|---------|
|
||||
| `NUnit` | 4.6.1 | Primary test framework. |
|
||||
| `NUnit3TestAdapter` | 6.2.0 | Visual Studio / `dotnet test` runner adapter. |
|
||||
| `NUnit.Analyzers` | 4.13.0 | Static analysis rules for NUnit test quality. |
|
||||
| `Moq` | 4.20.72 | Mocking framework for interface and logger substitution. |
|
||||
| `Microsoft.NET.Test.Sdk` | 18.6.0 | MSBuild targets and test-host runtime. |
|
||||
| `Microsoft.QualityTools.Testing.Fakes` | 18.1.1 | Shim-based isolation for static/sealed code. |
|
||||
| `Mongo2Go` | 4.1.0 | Ephemeral MongoDB instance for integration tests. |
|
||||
| `MongoMigrations.Core` | 4.0.15 | Migration script validation in integration tests. |
|
||||
| `coverlet.collector` | 10.0.1 | Code-coverage instrumentation for CI pipelines. |
|
||||
| `AuditLogs` | 1.0.59 | Audit logging used during service-level tests. |
|
||||
|
||||
---
|
||||
|
||||
## Test Architecture
|
||||
|
||||
### Layer Distribution
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Unit Tests │
|
||||
│ (fast, deterministic, no I/O) │
|
||||
│ • Domain entity factories & validation │
|
||||
│ • Service logic with Moq'd repositories │
|
||||
│ • Utility classes (CacheKeyClassifier, etc.) │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Integration Tests │
|
||||
│ (MongoDB-backed, startup/teardown cost) │
|
||||
│ • Repository CRUD round-trips │
|
||||
│ • Pagination, filtering, aggregation pipelines │
|
||||
│ • Migration script execution │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Module Tests │
|
||||
│ (in-memory device substitutes) │
|
||||
│ • FakeRelay outlet control sequences │
|
||||
│ • CacheService eviction & concurrency │
|
||||
│ • LockManagerService deadlock prevention │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Categorisation
|
||||
|
||||
| Category | Attribute | CI Inclusion |
|
||||
|----------|-----------|------------|
|
||||
| Unit | `[Category("Unit")]` (implicit) | Always |
|
||||
| Integration | `[Category("Integration")]` | Gated / nightly |
|
||||
| Customization | `[Category("Customization")]` | Deployment-specific |
|
||||
|
||||
### Concurrency Safety
|
||||
|
||||
- `[Parallelizable(ParallelScope.All)]` is applied at fixture level where tests are independent.
|
||||
- `IntegrationDb` is a `[SetUpFixture]` — one MongoDB runner per test run, not per test.
|
||||
- Each repository test class works on **disjoint document IDs** to avoid collisions.
|
||||
|
||||
---
|
||||
|
||||
## Test Data & Builders
|
||||
|
||||
### `IntegrationDb` — MongoDB Lifecycle
|
||||
|
||||
- `[OneTimeSetUp]` starts `MongoDbRunner`, configures BSON conventions, and opens `IntegrationTestDb`.
|
||||
- `[OneTimeTearDown]` disposes runner and client connections.
|
||||
- All repository fixtures implicitly share the same database but use unique collections per test class.
|
||||
|
||||
### `TestUtilities` — Entity Factories
|
||||
|
||||
Provides deterministic builders for:
|
||||
|
||||
- `Patient` with default demographics
|
||||
- `Admission` linked to a `PointOfCare`
|
||||
- `PointOfCare` with unit and section hierarchy
|
||||
- `Unit`, `Section`, `DisplayConfig`
|
||||
- `OptionList` master data
|
||||
- `Discharge`, `Diagnosis`, `Treatment` records
|
||||
|
||||
Every builder assigns deterministic `ObjectId` values so assertions are reproducible.
|
||||
|
||||
### `FakeLogger` — Log Capture
|
||||
|
||||
Implements `Serilog.ILogger` with:
|
||||
|
||||
- `Messages` list capturing every rendered log entry.
|
||||
- `IsEnabled()` returns `true` unconditionally.
|
||||
- `ForContext()` returns `this` (no-op enrichment).
|
||||
- Tests assert on `Messages.Contains(...)`, `Messages.Count`, or log level distribution.
|
||||
|
||||
---
|
||||
|
||||
## Running the Tests
|
||||
|
||||
### Full Suite
|
||||
|
||||
```bash
|
||||
cd adas-core.Test
|
||||
dotnet test --verbosity normal
|
||||
```
|
||||
|
||||
### Unit Only (skip integration)
|
||||
|
||||
```bash
|
||||
dotnet test --filter "Category!=Integration"
|
||||
```
|
||||
|
||||
### Integration Only
|
||||
|
||||
```bash
|
||||
dotnet test --filter "Category=Integration"
|
||||
```
|
||||
|
||||
### With Coverage
|
||||
|
||||
```bash
|
||||
dotnet test --collect:"XPlat Code Coverage"
|
||||
```
|
||||
|
||||
> Requires `coverlet.collector` and produces `coverage.cobertura.xml` in the `TestResults/` folder.
|
||||
|
||||
---
|
||||
|
||||
## Design Rules
|
||||
|
||||
1. **No External Network** — All tests must run without external MongoDB, Redis, RabbitMQ, or LDAP servers. `Mongo2Go`, `InMemoryLockProvider`, and `Moq` satisfy this.
|
||||
2. **Deterministic Fixtures** — `TestUtilities` builders always produce the same `ObjectId` and default values for the same inputs. No random data.
|
||||
3. **One Concern per Test** — Each `[Test]` asserts a single behavior. Compound assertions are allowed only when verifying correlated outcomes of the same operation.
|
||||
4. **Mock External Boundaries** — Services under test receive Moq'd `ILogger`, `IRepository`, and `IMessageService` instances. Integration tests may use real `MongoRepository` via `IntegrationDb`.
|
||||
5. **Category Tags** — Every repository or migration test MUST carry `[Category("Integration")]` so CI can filter slow tests.
|
||||
6. **Cleanup Guarantee** — `[OneTimeTearDown]` in `IntegrationDb` always disposes the `MongoDbRunner`. No orphaned processes.
|
||||
7. **FakeLogger Over Null Logger** — Service tests must pass a `FakeLogger` (or `Mock<ILogger>`) rather than `null` to constructors expecting `ILogger`.
|
||||
8. **No Production Dependencies in Tests** — The test project references `Domain`, `Infrastructure`, and `Host`, but must never be referenced **by** them. Tests are the outermost layer.
|
||||
9. **Customization Isolation** — Hospital-specific tests reside exclusively in `Customizations/{Site}/`. They validate site-specific formulas without polluting generic service tests.
|
||||
10. **Coverage Thresholds** — CI gates enforce minimum branch coverage on `Domain` and `Application` projects. New features without accompanying tests fail the build.
|
||||
|
||||
---
|
||||
|
||||
<p align="center">
|
||||
Back to <a href="../README.md">adas-core Root README</a>
|
||||
</p>
|
||||
@@ -14,26 +14,30 @@ namespace adas_core.Test.Repositories;
|
||||
[Category("Integration")]
|
||||
public class AdmissionRepositoryTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the integration test environment by resetting the admissions collection
|
||||
/// and seeding it with valid admission records to be used across the test fixture.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("admissions");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("admissions");
|
||||
|
||||
_repository = new AdmissionRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
var admissions = new List<Admission>
|
||||
public async Task Init()
|
||||
{
|
||||
TestUtilities.CreateValidAdmission(),
|
||||
TestUtilities.CreateValidAdmission(),
|
||||
TestUtilities.CreateValidAdmission()
|
||||
};
|
||||
|
||||
foreach (var admission in admissions) await _repository.InsertOneAsync(admission);
|
||||
}
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("admissions");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("admissions");
|
||||
|
||||
_repository = new AdmissionRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
var admissions = new List<Admission>
|
||||
{
|
||||
TestUtilities.CreateValidAdmission(),
|
||||
TestUtilities.CreateValidAdmission(),
|
||||
TestUtilities.CreateValidAdmission()
|
||||
};
|
||||
|
||||
foreach (var admission in admissions) await _repository.InsertOneAsync(admission);
|
||||
}
|
||||
|
||||
private AdmissionRepository _repository;
|
||||
private IOptions<ApiSettings> _optionsApiSettings;
|
||||
@@ -43,172 +47,206 @@ public class AdmissionRepositoryTest
|
||||
Admissions = "admissions"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="AdmissionRepository.InsertOneAsync"/> successfully persists a valid admission so that it can subsequently be retrieved by its identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task InsertOneAsync_Success()
|
||||
{
|
||||
// Arrange
|
||||
var admission = TestUtilities.CreateValidAdmission();
|
||||
|
||||
// Act
|
||||
await _repository.InsertOneAsync(admission);
|
||||
|
||||
// Assert
|
||||
var result = await _repository.FindById(admission.Id);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result?.Id, Is.EqualTo(admission.Id));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Delete_Success()
|
||||
{
|
||||
// Arrange
|
||||
var admission = TestUtilities.CreateValidAdmission();
|
||||
await _repository.InsertOneAsync(admission);
|
||||
|
||||
// Act
|
||||
await _repository.Delete(admission.Id);
|
||||
|
||||
// Assert
|
||||
var result = await _repository.FindById(admission.Id);
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Update_Success()
|
||||
{
|
||||
// Arrange
|
||||
var admission = TestUtilities.CreateValidAdmission();
|
||||
await _repository.InsertOneAsync(admission);
|
||||
|
||||
// Modify the admission
|
||||
admission.DiagnosisAux = "Updated value";
|
||||
|
||||
// Act
|
||||
await _repository.Update(admission);
|
||||
|
||||
// Assert
|
||||
var updatedAdmission = await _repository.FindById(admission.Id);
|
||||
Assert.That(updatedAdmission, Is.Not.Null);
|
||||
Assert.That(updatedAdmission?.DiagnosisAux, Is.EqualTo(admission.DiagnosisAux));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task UpdateLocation_Success()
|
||||
{
|
||||
// Arrange
|
||||
var admission = TestUtilities.CreateValidAdmission();
|
||||
var originalLocationId = ObjectId.GenerateNewId();
|
||||
var newLocationId = ObjectId.GenerateNewId();
|
||||
|
||||
admission.PointOfCareId = originalLocationId;
|
||||
await _repository.InsertOneAsync(admission);
|
||||
|
||||
// Act
|
||||
await _repository.UpdateLocation(admission.Id, newLocationId);
|
||||
|
||||
// Assert
|
||||
var updatedAdmission = await _repository.FindById(admission.Id);
|
||||
Assert.That(updatedAdmission, Is.Not.Null);
|
||||
Assert.That(newLocationId, Is.EqualTo(updatedAdmission?.PointOfCareId));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task UpdatePatient_Success()
|
||||
{
|
||||
// Arrange
|
||||
var admission = TestUtilities.CreateValidAdmission();
|
||||
var newPatient = new Person
|
||||
public async Task InsertOneAsync_Success()
|
||||
{
|
||||
LastName = "Doe",
|
||||
FirstName = "John",
|
||||
BirthDate = new DateTime(1990, 1, 1),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(admission);
|
||||
|
||||
// Act
|
||||
await _repository.UpdatePatient(admission.Id, newPatient);
|
||||
|
||||
// Assert
|
||||
var updatedAdmission = await _repository.FindById(admission.Id);
|
||||
Assert.That(updatedAdmission, Is.Not.Null);
|
||||
Assert.That(updatedAdmission?.Person, Is.Not.Null);
|
||||
Assert.That(updatedAdmission?.Person?.FirstName, Is.EqualTo(newPatient.FirstName));
|
||||
}
|
||||
// Arrange
|
||||
var admission = TestUtilities.CreateValidAdmission();
|
||||
|
||||
// Act
|
||||
await _repository.InsertOneAsync(admission);
|
||||
|
||||
// Assert
|
||||
var result = await _repository.FindById(admission.Id);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result?.Id, Is.EqualTo(admission.Id));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository successfully deletes an admission record, ensuring that the deleted admission can no longer be retrieved by its identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindAll_Success()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindAll();
|
||||
|
||||
// Assert
|
||||
var admissions = result as Admission[] ?? result.ToArray();
|
||||
Assert.That(admissions, Is.Not.Null);
|
||||
Assert.That(admissions, Is.Not.Empty);
|
||||
Assert.That(admissions.Count(), Is.EqualTo(3));
|
||||
}
|
||||
public async Task Delete_Success()
|
||||
{
|
||||
// Arrange
|
||||
var admission = TestUtilities.CreateValidAdmission();
|
||||
await _repository.InsertOneAsync(admission);
|
||||
|
||||
// Act
|
||||
await _repository.Delete(admission.Id);
|
||||
|
||||
// Assert
|
||||
var result = await _repository.FindById(admission.Id);
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="Admission"/> updates are persisted successfully by inserting an admission, modifying one of its fields, and asserting that the updated value is retrieved.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindById_Success()
|
||||
{
|
||||
// Arrange
|
||||
var admission = TestUtilities.CreateValidAdmission();
|
||||
await _repository.InsertOneAsync(admission);
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindById(admission.Id);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(admission.Id, Is.EqualTo(result?.Id));
|
||||
}
|
||||
public async Task Update_Success()
|
||||
{
|
||||
// Arrange
|
||||
var admission = TestUtilities.CreateValidAdmission();
|
||||
await _repository.InsertOneAsync(admission);
|
||||
|
||||
// Modify the admission
|
||||
admission.DiagnosisAux = "Updated value";
|
||||
|
||||
// Act
|
||||
await _repository.Update(admission);
|
||||
|
||||
// Assert
|
||||
var updatedAdmission = await _repository.FindById(admission.Id);
|
||||
Assert.That(updatedAdmission, Is.Not.Null);
|
||||
Assert.That(updatedAdmission?.DiagnosisAux, Is.EqualTo(admission.DiagnosisAux));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="AdmissionRepository.UpdateLocation"/> successfully updates the
|
||||
/// <c>PointOfCareId</c> of an existing admission to the specified new location identifier
|
||||
/// and that the change is persisted in the repository.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindById_NotFound()
|
||||
{
|
||||
// Arrange
|
||||
var nonExistingId = ObjectId.GenerateNewId();
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindById(nonExistingId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
public async Task UpdateLocation_Success()
|
||||
{
|
||||
// Arrange
|
||||
var admission = TestUtilities.CreateValidAdmission();
|
||||
var originalLocationId = ObjectId.GenerateNewId();
|
||||
var newLocationId = ObjectId.GenerateNewId();
|
||||
|
||||
admission.PointOfCareId = originalLocationId;
|
||||
await _repository.InsertOneAsync(admission);
|
||||
|
||||
// Act
|
||||
await _repository.UpdateLocation(admission.Id, newLocationId);
|
||||
|
||||
// Assert
|
||||
var updatedAdmission = await _repository.FindById(admission.Id);
|
||||
Assert.That(updatedAdmission, Is.Not.Null);
|
||||
Assert.That(newLocationId, Is.EqualTo(updatedAdmission?.PointOfCareId));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository successfully updates the patient information of an existing admission,
|
||||
/// ensuring the updated admission can be retrieved and reflects the new patient's details.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByNhc_Success()
|
||||
{
|
||||
// Arrange
|
||||
var admission = TestUtilities.CreateValidAdmission();
|
||||
await _repository.InsertOneAsync(admission);
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindByNhc(admission.Nhc);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(admission.Nhc, Is.EqualTo(result?.Nhc));
|
||||
}
|
||||
public async Task UpdatePatient_Success()
|
||||
{
|
||||
// Arrange
|
||||
var admission = TestUtilities.CreateValidAdmission();
|
||||
var newPatient = new Person
|
||||
{
|
||||
LastName = "Doe",
|
||||
FirstName = "John",
|
||||
BirthDate = new DateTime(1990, 1, 1),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(admission);
|
||||
|
||||
// Act
|
||||
await _repository.UpdatePatient(admission.Id, newPatient);
|
||||
|
||||
// Assert
|
||||
var updatedAdmission = await _repository.FindById(admission.Id);
|
||||
Assert.That(updatedAdmission, Is.Not.Null);
|
||||
Assert.That(updatedAdmission?.Person, Is.Not.Null);
|
||||
Assert.That(updatedAdmission?.Person?.FirstName, Is.EqualTo(newPatient.FirstName));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's FindAll operation successfully retrieves all admissions, returning a non-empty collection of exactly three records.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByNhc_NotFound()
|
||||
{
|
||||
// Arrange
|
||||
var nonExistingNhc = "non-existing-nhc";
|
||||
public async Task FindAll_Success()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindAll();
|
||||
|
||||
// Assert
|
||||
var admissions = result as Admission[] ?? result.ToArray();
|
||||
Assert.That(admissions, Is.Not.Null);
|
||||
Assert.That(admissions, Is.Not.Empty);
|
||||
Assert.That(admissions.Count(), Is.EqualTo(3));
|
||||
}
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindByNhc(nonExistingNhc);
|
||||
/// <summary>
|
||||
/// Verifies that the repository successfully retrieves an admission by its unique identifier after it has been inserted.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindById_Success()
|
||||
{
|
||||
// Arrange
|
||||
var admission = TestUtilities.CreateValidAdmission();
|
||||
await _repository.InsertOneAsync(admission);
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindById(admission.Id);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(admission.Id, Is.EqualTo(result?.Id));
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
/// <summary>
|
||||
/// Verifies that the repository's <c>FindById</c> method returns <c>null</c> when queried with a non-existing identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindById_NotFound()
|
||||
{
|
||||
// Arrange
|
||||
var nonExistingId = ObjectId.GenerateNewId();
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindById(nonExistingId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="AdmissionRepository.FindByNhc"/> successfully retrieves an admission record from the repository using its NHC identifier.
|
||||
/// Confirms that the returned record is not null and that the NHC of the retrieved admission matches the one used in the lookup.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByNhc_Success()
|
||||
{
|
||||
// Arrange
|
||||
var admission = TestUtilities.CreateValidAdmission();
|
||||
await _repository.InsertOneAsync(admission);
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindByNhc(admission.Nhc);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(admission.Nhc, Is.EqualTo(result?.Nhc));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="AdmissionRepository"/>.<c>FindByNhc</c> returns <c>null</c> when the provided NHC does not exist in the data source.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByNhc_NotFound()
|
||||
{
|
||||
// Arrange
|
||||
var nonExistingNhc = "non-existing-nhc";
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindByNhc(nonExistingNhc);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
// [Test]
|
||||
// public async Task FindByLocation_Success()
|
||||
@@ -271,120 +309,142 @@ public class AdmissionRepositoryTest
|
||||
// Assert.That(resultList?.Count(), Is.EqualTo(2));
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that inserting a valid admission through the repository returns the same admission and persists it so it can be retrieved by its identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task InsertOneAsyncAndReturn_Success()
|
||||
{
|
||||
// Arrange
|
||||
var admission = TestUtilities.CreateValidAdmission();
|
||||
|
||||
// Act
|
||||
var result = await _repository.InsertOneAsyncAndReturn(admission);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.EqualTo(admission));
|
||||
var retrievedAdmission = await _repository.FindById(admission.Id);
|
||||
Assert.That(retrievedAdmission, Is.Not.Null);
|
||||
Assert.That(retrievedAdmission?.Id, Is.EqualTo(admission.Id));
|
||||
}
|
||||
public async Task InsertOneAsyncAndReturn_Success()
|
||||
{
|
||||
// Arrange
|
||||
var admission = TestUtilities.CreateValidAdmission();
|
||||
|
||||
// Act
|
||||
var result = await _repository.InsertOneAsyncAndReturn(admission);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.EqualTo(admission));
|
||||
var retrievedAdmission = await _repository.FindById(admission.Id);
|
||||
Assert.That(retrievedAdmission, Is.Not.Null);
|
||||
Assert.That(retrievedAdmission?.Id, Is.EqualTo(admission.Id));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Tests that the repository's <c>GetAdmissionByUnitIdWithOutPoC</c> method returns only the admissions matching the specified unit identifier
|
||||
/// while excluding admissions that have an associated point-of-care identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetAdmissionByUnitIdWithOutPoC_Success()
|
||||
{
|
||||
// Arrange
|
||||
var unitId = ObjectId.GenerateNewId();
|
||||
var admission1 = TestUtilities.CreateValidAdmission();
|
||||
admission1.UnitId = unitId;
|
||||
admission1.PointOfCareId = null;
|
||||
|
||||
var admission2 = TestUtilities.CreateValidAdmission();
|
||||
admission2.UnitId = ObjectId.GenerateNewId();
|
||||
admission2.PointOfCareId = ObjectId.GenerateNewId();
|
||||
|
||||
await _repository.InsertOneAsync(admission1);
|
||||
await _repository.InsertOneAsync(admission2);
|
||||
|
||||
// Act
|
||||
var result = await _repository.GetAdmissionByUnitIdWithOutPoC(unitId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Count, Is.EqualTo(1));
|
||||
Assert.That(result[0].UnitId, Is.EqualTo(unitId));
|
||||
Assert.That(result[0].PointOfCareId, Is.Null);
|
||||
}
|
||||
public async Task GetAdmissionByUnitIdWithOutPoC_Success()
|
||||
{
|
||||
// Arrange
|
||||
var unitId = ObjectId.GenerateNewId();
|
||||
var admission1 = TestUtilities.CreateValidAdmission();
|
||||
admission1.UnitId = unitId;
|
||||
admission1.PointOfCareId = null;
|
||||
|
||||
var admission2 = TestUtilities.CreateValidAdmission();
|
||||
admission2.UnitId = ObjectId.GenerateNewId();
|
||||
admission2.PointOfCareId = ObjectId.GenerateNewId();
|
||||
|
||||
await _repository.InsertOneAsync(admission1);
|
||||
await _repository.InsertOneAsync(admission2);
|
||||
|
||||
// Act
|
||||
var result = await _repository.GetAdmissionByUnitIdWithOutPoC(unitId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Count, Is.EqualTo(1));
|
||||
Assert.That(result[0].UnitId, Is.EqualTo(unitId));
|
||||
Assert.That(result[0].PointOfCareId, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>GetAdmissionByUnitIdWithOutPoC</c> returns an empty result set (instead of null) when no admissions match the provided unit identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetAdmissionByUnitIdWithOutPoC_NoMatch()
|
||||
{
|
||||
// Arrange
|
||||
var unitId = ObjectId.GenerateNewId();
|
||||
|
||||
// Act
|
||||
var result = await _repository.GetAdmissionByUnitIdWithOutPoC(unitId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
public async Task GetAdmissionByUnitIdWithOutPoC_NoMatch()
|
||||
{
|
||||
// Arrange
|
||||
var unitId = ObjectId.GenerateNewId();
|
||||
|
||||
// Act
|
||||
var result = await _repository.GetAdmissionByUnitIdWithOutPoC(unitId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's <c>FindByPointOfCareId</c> method successfully retrieves the admission matching the specified point of care identifier, returning a single result and excluding admissions associated with different point of care identifiers.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByPointOfCareId_Success()
|
||||
{
|
||||
var pocId = ObjectId.GenerateNewId();
|
||||
var admission1 = TestUtilities.CreateValidAdmission();
|
||||
admission1.PointOfCareId = pocId;
|
||||
|
||||
var admission2 = TestUtilities.CreateValidAdmission();
|
||||
admission2.PointOfCareId = ObjectId.GenerateNewId();
|
||||
|
||||
await _repository.InsertOneAsync(admission1);
|
||||
await _repository.InsertOneAsync(admission2);
|
||||
|
||||
var result = await _repository.FindByPointOfCareId(pocId);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Count, Is.EqualTo(1));
|
||||
Assert.That(result[0].PointOfCareId, Is.EqualTo(pocId));
|
||||
}
|
||||
public async Task FindByPointOfCareId_Success()
|
||||
{
|
||||
var pocId = ObjectId.GenerateNewId();
|
||||
var admission1 = TestUtilities.CreateValidAdmission();
|
||||
admission1.PointOfCareId = pocId;
|
||||
|
||||
var admission2 = TestUtilities.CreateValidAdmission();
|
||||
admission2.PointOfCareId = ObjectId.GenerateNewId();
|
||||
|
||||
await _repository.InsertOneAsync(admission1);
|
||||
await _repository.InsertOneAsync(admission2);
|
||||
|
||||
var result = await _repository.FindByPointOfCareId(pocId);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Count, Is.EqualTo(1));
|
||||
Assert.That(result[0].PointOfCareId, Is.EqualTo(pocId));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="AdmissionRepository"/>.FindByPointOfCareId returns a non-null empty collection when no point of care matches the provided identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByPointOfCareId_NoMatch()
|
||||
{
|
||||
var pocId = ObjectId.GenerateNewId();
|
||||
|
||||
var result = await _repository.FindByPointOfCareId(pocId);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
public async Task FindByPointOfCareId_NoMatch()
|
||||
{
|
||||
var pocId = ObjectId.GenerateNewId();
|
||||
|
||||
var result = await _repository.FindByPointOfCareId(pocId);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="AdmissionRepository"/>.<c>FindByDiagnosis</c> successfully returns a non-null result when retrieving admissions matching the specified diagnosis value.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByDiagnosis_Success()
|
||||
{
|
||||
var diagnosis = "SomeDiagnosis";
|
||||
var admission1 = TestUtilities.CreateValidAdmission();
|
||||
admission1.Diagnosis = TestUtilities.CreateValidOptionList();
|
||||
|
||||
var admission2 = TestUtilities.CreateValidAdmission();
|
||||
admission2.Diagnosis = TestUtilities.CreateValidOptionList();
|
||||
|
||||
await _repository.InsertOneAsync(admission1);
|
||||
await _repository.InsertOneAsync(admission2);
|
||||
|
||||
var result = await _repository.FindByDiagnosis(diagnosis);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
public async Task FindByDiagnosis_Success()
|
||||
{
|
||||
var diagnosis = "SomeDiagnosis";
|
||||
var admission1 = TestUtilities.CreateValidAdmission();
|
||||
admission1.Diagnosis = TestUtilities.CreateValidOptionList();
|
||||
|
||||
var admission2 = TestUtilities.CreateValidAdmission();
|
||||
admission2.Diagnosis = TestUtilities.CreateValidOptionList();
|
||||
|
||||
await _repository.InsertOneAsync(admission1);
|
||||
await _repository.InsertOneAsync(admission2);
|
||||
|
||||
var result = await _repository.FindByDiagnosis(diagnosis);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="AdmissionRepository"/>.<c>FindByDiagnosis</c> returns an empty collection when no entity matches the provided diagnosis.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByDiagnosis_NoMatch()
|
||||
{
|
||||
var diagnosis = "NonExistentDiagnosis";
|
||||
|
||||
var result = await _repository.FindByDiagnosis(diagnosis);
|
||||
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
public async Task FindByDiagnosis_NoMatch()
|
||||
{
|
||||
var diagnosis = "NonExistentDiagnosis";
|
||||
|
||||
var result = await _repository.FindByDiagnosis(diagnosis);
|
||||
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
}
|
||||
@@ -15,46 +15,51 @@ namespace adas_core.Test.Repositories;
|
||||
[Category("Integration")]
|
||||
public class AlarmRepositoryTest
|
||||
{
|
||||
/// <summary>
|
||||
/// One-time test setup that initializes the alarm repository with two sample
|
||||
/// <see cref="PatientObservationAlarm"/> records by resetting the target
|
||||
/// collection and inserting the test data for use across the test fixture.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
|
||||
var pObsAlarm1 = new PatientObservationAlarm
|
||||
public async Task Init()
|
||||
{
|
||||
Id = Id,
|
||||
PatientId = PatientId,
|
||||
Code = "code1",
|
||||
CodingSystem = "SNM",
|
||||
Name = "name1",
|
||||
Time = Now,
|
||||
Value = "value1",
|
||||
SystemId = "systemId1"
|
||||
};
|
||||
|
||||
var pObsAlarm2 = new PatientObservationAlarm
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = PatientId,
|
||||
Code = "code2",
|
||||
CodingSystem = "SNM",
|
||||
Name = "name2",
|
||||
Time = Now,
|
||||
Value = "value2",
|
||||
SystemId = "systemId2"
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("patients_alarms");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("patients_alarms");
|
||||
|
||||
_logger = new Mock<ILogger<AlarmRepository>>();
|
||||
|
||||
_repository = new AlarmRepository(_optionsApiSettings, IntegrationDb.Database, _logger.Object);
|
||||
|
||||
await _repository.InsertOneAsync(pObsAlarm1);
|
||||
await _repository.InsertOneAsync(pObsAlarm2);
|
||||
}
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
|
||||
var pObsAlarm1 = new PatientObservationAlarm
|
||||
{
|
||||
Id = Id,
|
||||
PatientId = PatientId,
|
||||
Code = "code1",
|
||||
CodingSystem = "SNM",
|
||||
Name = "name1",
|
||||
Time = Now,
|
||||
Value = "value1",
|
||||
SystemId = "systemId1"
|
||||
};
|
||||
|
||||
var pObsAlarm2 = new PatientObservationAlarm
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = PatientId,
|
||||
Code = "code2",
|
||||
CodingSystem = "SNM",
|
||||
Name = "name2",
|
||||
Time = Now,
|
||||
Value = "value2",
|
||||
SystemId = "systemId2"
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("patients_alarms");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("patients_alarms");
|
||||
|
||||
_logger = new Mock<ILogger<AlarmRepository>>();
|
||||
|
||||
_repository = new AlarmRepository(_optionsApiSettings, IntegrationDb.Database, _logger.Object);
|
||||
|
||||
await _repository.InsertOneAsync(pObsAlarm1);
|
||||
await _repository.InsertOneAsync(pObsAlarm2);
|
||||
}
|
||||
|
||||
private AlarmRepository _repository;
|
||||
|
||||
@@ -70,164 +75,184 @@ public class AlarmRepositoryTest
|
||||
private static readonly ObjectId PatientId = ObjectId.GenerateNewId();
|
||||
private static readonly ObjectId Id = ObjectId.GenerateNewId();
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="AlarmRepository.AggregatedPatientLastObservationsByField"/> returns an empty list when no observations match the provided field filter criteria.
|
||||
/// </summary>
|
||||
/// <param name="filter">The collection of <see cref="Field"/> objects used to filter observations; contains a single non-existent field to ensure no matches are found.</param>
|
||||
/// <returns>A task that completes after asserting the repository returns a non-null but empty result.</returns>
|
||||
[Test]
|
||||
public async Task AggregatedPatientLastObservationsByField_Not_Found_Returns_Empty_List()
|
||||
{
|
||||
var filter = new List<Field>
|
||||
public async Task AggregatedPatientLastObservationsByField_Not_Found_Returns_Empty_List()
|
||||
{
|
||||
new()
|
||||
var filter = new List<Field>
|
||||
{
|
||||
Name = "name100",
|
||||
Last = 2,
|
||||
OnlyExpired = false
|
||||
}
|
||||
};
|
||||
|
||||
var result = await _repository.AggregatedPatientLastObservationsByField(PatientId, filter);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
new()
|
||||
{
|
||||
Name = "name100",
|
||||
Last = 2,
|
||||
OnlyExpired = false
|
||||
}
|
||||
};
|
||||
|
||||
var result = await _repository.AggregatedPatientLastObservationsByField(PatientId, filter);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that AggregatedPatientLastObservationsByField returns exactly one aggregated result when matching last observations are found for the specified patient and field filter.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task AggregatedPatientLastObservationsByField_Found_Returns_1()
|
||||
{
|
||||
var filter = new List<Field>
|
||||
public async Task AggregatedPatientLastObservationsByField_Found_Returns_1()
|
||||
{
|
||||
new()
|
||||
var filter = new List<Field>
|
||||
{
|
||||
Name = "name1",
|
||||
Last = 2,
|
||||
OnlyExpired = false
|
||||
}
|
||||
};
|
||||
|
||||
var result = await _repository.AggregatedPatientLastObservationsByField(PatientId, filter);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Count(), Is.EqualTo(1));
|
||||
}
|
||||
new()
|
||||
{
|
||||
Name = "name1",
|
||||
Last = 2,
|
||||
OnlyExpired = false
|
||||
}
|
||||
};
|
||||
|
||||
var result = await _repository.AggregatedPatientLastObservationsByField(PatientId, filter);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Count(), Is.EqualTo(1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="AlarmRepository.AggregatedPatientLastObservationsByField"/> returns a non-null collection containing an entry for each matching field in the filter when observations are found for the given patient.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task AggregatedPatientLastObservationsByField_Found_Returns_2()
|
||||
{
|
||||
var filter = new List<Field>
|
||||
public async Task AggregatedPatientLastObservationsByField_Found_Returns_2()
|
||||
{
|
||||
new()
|
||||
var filter = new List<Field>
|
||||
{
|
||||
Name = "name1",
|
||||
Last = 1,
|
||||
OnlyExpired = false
|
||||
},
|
||||
new()
|
||||
{
|
||||
Name = "name2",
|
||||
Last = 1,
|
||||
OnlyExpired = false
|
||||
}
|
||||
};
|
||||
|
||||
var result = await _repository.AggregatedPatientLastObservationsByField(PatientId, filter);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Count(), Is.EqualTo(2));
|
||||
}
|
||||
new()
|
||||
{
|
||||
Name = "name1",
|
||||
Last = 1,
|
||||
OnlyExpired = false
|
||||
},
|
||||
new()
|
||||
{
|
||||
Name = "name2",
|
||||
Last = 1,
|
||||
OnlyExpired = false
|
||||
}
|
||||
};
|
||||
|
||||
var result = await _repository.AggregatedPatientLastObservationsByField(PatientId, filter);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Count(), Is.EqualTo(2));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository returns an empty list when querying aggregated patient last observations by field with a filter that specifies OnlyExpired as true, and the matching patient observation alarm is expired.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task AggregatedPatientLastObservationsByField_AllExpired_Returns_Empty_List()
|
||||
{
|
||||
var expiredTime = Now.AddDays(-1); // Set a time in the past to simulate expiration
|
||||
|
||||
var expiredObs = new PatientObservationAlarm
|
||||
public async Task AggregatedPatientLastObservationsByField_AllExpired_Returns_Empty_List()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = PatientId,
|
||||
Code = "code3",
|
||||
CodingSystem = "SNM",
|
||||
Name = "name3",
|
||||
Time = expiredTime,
|
||||
Value = "value3",
|
||||
SystemId = "systemId3",
|
||||
Expired = true
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(expiredObs);
|
||||
|
||||
var filter = new List<Field>
|
||||
{
|
||||
new()
|
||||
var expiredTime = Now.AddDays(-1); // Set a time in the past to simulate expiration
|
||||
|
||||
var expiredObs = new PatientObservationAlarm
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = PatientId,
|
||||
Code = "code3",
|
||||
CodingSystem = "SNM",
|
||||
Name = "name3",
|
||||
Last = 2,
|
||||
OnlyExpired = true
|
||||
}
|
||||
};
|
||||
|
||||
var result = await _repository.AggregatedPatientLastObservationsByField(PatientId, filter);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task AggregatedPatientLastObservationsByField_MultipleObservations_Returns_Most_Recent()
|
||||
{
|
||||
var oldTime = Now.AddMinutes(-10); // Set an older time
|
||||
|
||||
var oldObs = new PatientObservationAlarm
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = PatientId,
|
||||
Code = "code4",
|
||||
CodingSystem = "SNM",
|
||||
Name = "name4",
|
||||
Time = oldTime,
|
||||
Value = "value4",
|
||||
SystemId = "systemId4"
|
||||
};
|
||||
|
||||
var newObs = new PatientObservationAlarm
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = PatientId,
|
||||
Code = "code4",
|
||||
CodingSystem = "SNM",
|
||||
Name = "name4",
|
||||
Time = Now,
|
||||
Value = "value5",
|
||||
SystemId = "systemId5"
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(oldObs);
|
||||
await _repository.InsertOneAsync(newObs);
|
||||
|
||||
var filter = new List<Field>
|
||||
{
|
||||
new()
|
||||
Time = expiredTime,
|
||||
Value = "value3",
|
||||
SystemId = "systemId3",
|
||||
Expired = true
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(expiredObs);
|
||||
|
||||
var filter = new List<Field>
|
||||
{
|
||||
Name = "name4",
|
||||
Last = 1,
|
||||
OnlyExpired = false
|
||||
}
|
||||
};
|
||||
|
||||
var result = await _repository.AggregatedPatientLastObservationsByField(PatientId, filter);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
|
||||
Assert.That(result, Has.Count.EqualTo(1));
|
||||
Assert.That(result.First().Value, Is.EqualTo("value5")); // Ensure the most recent observation is returned
|
||||
};
|
||||
}
|
||||
new()
|
||||
{
|
||||
Name = "name3",
|
||||
Last = 2,
|
||||
OnlyExpired = true
|
||||
}
|
||||
};
|
||||
|
||||
var result = await _repository.AggregatedPatientLastObservationsByField(PatientId, filter);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that when multiple observations exist for the same field, the aggregation returns only the most recent observation based on the timestamp.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task AggregatedPatientLastObservationsByField_FilterObservations_Null_Returns_All()
|
||||
{
|
||||
var result = await _repository.AggregatedPatientLastObservationsByField(PatientId);
|
||||
public async Task AggregatedPatientLastObservationsByField_MultipleObservations_Returns_Most_Recent()
|
||||
{
|
||||
var oldTime = Now.AddMinutes(-10); // Set an older time
|
||||
|
||||
var oldObs = new PatientObservationAlarm
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = PatientId,
|
||||
Code = "code4",
|
||||
CodingSystem = "SNM",
|
||||
Name = "name4",
|
||||
Time = oldTime,
|
||||
Value = "value4",
|
||||
SystemId = "systemId4"
|
||||
};
|
||||
|
||||
var newObs = new PatientObservationAlarm
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = PatientId,
|
||||
Code = "code4",
|
||||
CodingSystem = "SNM",
|
||||
Name = "name4",
|
||||
Time = Now,
|
||||
Value = "value5",
|
||||
SystemId = "systemId5"
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(oldObs);
|
||||
await _repository.InsertOneAsync(newObs);
|
||||
|
||||
var filter = new List<Field>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Name = "name4",
|
||||
Last = 1,
|
||||
OnlyExpired = false
|
||||
}
|
||||
};
|
||||
|
||||
var result = await _repository.AggregatedPatientLastObservationsByField(PatientId, filter);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
|
||||
Assert.That(result, Has.Count.EqualTo(1));
|
||||
Assert.That(result.First().Value, Is.EqualTo("value5")); // Ensure the most recent observation is returned
|
||||
};
|
||||
}
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Not.Empty); // Ensure it returns all observations for the patient
|
||||
}
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="AlarmRepository.AggregatedPatientLastObservationsByField"/> returns all of a patient's last observations when no field filter is provided.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task AggregatedPatientLastObservationsByField_FilterObservations_Null_Returns_All()
|
||||
{
|
||||
var result = await _repository.AggregatedPatientLastObservationsByField(PatientId);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Not.Empty); // Ensure it returns all observations for the patient
|
||||
}
|
||||
}
|
||||
@@ -13,53 +13,61 @@ namespace adas_core.Test.Repositories;
|
||||
[Category("Integration")]
|
||||
public class AppointmentArchiveRepositoryTest
|
||||
{
|
||||
/// <summary>
|
||||
/// One-time test setup that initializes the appointments archive collection with two seed
|
||||
/// <see cref="PatientAppointment"/> records — a minimal appointment and a fully populated one with
|
||||
/// visit number, reason, and resource group location — for use by integration tests against
|
||||
/// <see cref="AppointmentArchiveRepository"/>.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="Task"/> that completes when the collection has been recreated and both
|
||||
/// seed appointments have been inserted.</returns>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var patient = new Person
|
||||
public async Task Init()
|
||||
{
|
||||
FirstName = "firstName",
|
||||
SecondName = "secondName",
|
||||
BirthDate = Now.AddYears(-10),
|
||||
Gender = PatientEnum.Gender.Female,
|
||||
Ids = new Dictionary<string, string> { { "MR", "123456" }, { "VN", "654321" } }
|
||||
};
|
||||
|
||||
PatientAppointment testPatientAppointment = new()
|
||||
{
|
||||
PatientId = PatientId,
|
||||
Patient = patient,
|
||||
CreateTime = Now.AddHours(-2),
|
||||
UpdateTime = Now.AddHours(-2)
|
||||
};
|
||||
|
||||
PatientAppointment testPatientAppointment2 = new()
|
||||
{
|
||||
PatientId = PatientId,
|
||||
Patient = patient,
|
||||
CreateTime = Now.AddHours(-3),
|
||||
UpdateTime = Now.AddHours(-3),
|
||||
VisitNumber = "654321",
|
||||
AppointmentReason = "appointmentReason",
|
||||
ResourceGroups =
|
||||
[
|
||||
new PatientAppointmentResourceGroup
|
||||
{
|
||||
Locations = [new PatientLocation("UCI5C", "Box4")]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("patients_appointments");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("patients_appointments");
|
||||
|
||||
_repository = new AppointmentArchiveRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(testPatientAppointment);
|
||||
await _repository.InsertOneAsync(testPatientAppointment2);
|
||||
}
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var patient = new Person
|
||||
{
|
||||
FirstName = "firstName",
|
||||
SecondName = "secondName",
|
||||
BirthDate = Now.AddYears(-10),
|
||||
Gender = PatientEnum.Gender.Female,
|
||||
Ids = new Dictionary<string, string> { { "MR", "123456" }, { "VN", "654321" } }
|
||||
};
|
||||
|
||||
PatientAppointment testPatientAppointment = new()
|
||||
{
|
||||
PatientId = PatientId,
|
||||
Patient = patient,
|
||||
CreateTime = Now.AddHours(-2),
|
||||
UpdateTime = Now.AddHours(-2)
|
||||
};
|
||||
|
||||
PatientAppointment testPatientAppointment2 = new()
|
||||
{
|
||||
PatientId = PatientId,
|
||||
Patient = patient,
|
||||
CreateTime = Now.AddHours(-3),
|
||||
UpdateTime = Now.AddHours(-3),
|
||||
VisitNumber = "654321",
|
||||
AppointmentReason = "appointmentReason",
|
||||
ResourceGroups =
|
||||
[
|
||||
new PatientAppointmentResourceGroup
|
||||
{
|
||||
Locations = [new PatientLocation("UCI5C", "Box4")]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("patients_appointments");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("patients_appointments");
|
||||
|
||||
_repository = new AppointmentArchiveRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(testPatientAppointment);
|
||||
await _repository.InsertOneAsync(testPatientAppointment2);
|
||||
}
|
||||
|
||||
private AppointmentArchiveRepository _repository;
|
||||
|
||||
@@ -75,19 +83,24 @@ public class AppointmentArchiveRepositoryTest
|
||||
private static readonly ObjectId PatientId = ObjectId.GenerateNewId();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's <c>DeleteBeforeDate</c> method correctly removes all records
|
||||
/// with a timestamp earlier than the specified cutoff date (two hours before the current time),
|
||||
/// while retaining records dated at or after the cutoff for the given patient.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task DeleteBeforeDate()
|
||||
{
|
||||
var result = await _repository.Collection.FindAsync(p => p.PatientId == PatientId);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.ToList(), Has.Count.GreaterThan(1));
|
||||
|
||||
await _repository.DeleteBeforeDate(Now.AddHours(-2));
|
||||
|
||||
var resultDelete = await _repository.Collection.FindAsync(p => p.PatientId == PatientId);
|
||||
|
||||
Assert.That(resultDelete, Is.Not.Null);
|
||||
Assert.That(resultDelete.ToList(), Has.Count.EqualTo(1));
|
||||
}
|
||||
public async Task DeleteBeforeDate()
|
||||
{
|
||||
var result = await _repository.Collection.FindAsync(p => p.PatientId == PatientId);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.ToList(), Has.Count.GreaterThan(1));
|
||||
|
||||
await _repository.DeleteBeforeDate(Now.AddHours(-2));
|
||||
|
||||
var resultDelete = await _repository.Collection.FindAsync(p => p.PatientId == PatientId);
|
||||
|
||||
Assert.That(resultDelete, Is.Not.Null);
|
||||
Assert.That(resultDelete.ToList(), Has.Count.EqualTo(1));
|
||||
}
|
||||
}
|
||||
@@ -12,53 +12,56 @@ namespace adas_core.Test.Repositories;
|
||||
[Category("Integration")]
|
||||
public class AppointmentRepositoryTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Performs one-time setup for integration tests by resetting the patients_appointments collection and seeding it with two test patient appointments: one with minimal fields and another extended with visit number, appointment reason, and resource groups.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var patient = new Person
|
||||
public async Task Init()
|
||||
{
|
||||
FirstName = "firstName",
|
||||
SecondName = "secondName",
|
||||
BirthDate = Now.AddYears(-10),
|
||||
Gender = PatientEnum.Gender.Female,
|
||||
Ids = new Dictionary<string, string> { { "MR", "123456" }, { "VN", "654321" } }
|
||||
};
|
||||
|
||||
var testPatientAppointment = new PatientAppointment
|
||||
{
|
||||
PatientId = PatientId,
|
||||
Patient = patient,
|
||||
CreateTime = Now.AddHours(-2),
|
||||
UpdateTime = Now.AddHours(-2)
|
||||
};
|
||||
|
||||
var testPatientAppointment2 = new PatientAppointment
|
||||
{
|
||||
PatientId = PatientId,
|
||||
Patient = patient,
|
||||
CreateTime = Now.AddHours(-3),
|
||||
UpdateTime = Now.AddHours(-3),
|
||||
VisitNumber = "654321",
|
||||
AppointmentReason = "appointmentReason",
|
||||
ResourceGroups =
|
||||
[
|
||||
new PatientAppointmentResourceGroup
|
||||
{
|
||||
Locations = [new PatientLocation("UCI5C", "Box4")]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("patients_appointments");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("patients_appointments");
|
||||
|
||||
_repository = new AppointmentRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(testPatientAppointment);
|
||||
await _repository.InsertOneAsync(testPatientAppointment2);
|
||||
}
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var patient = new Person
|
||||
{
|
||||
FirstName = "firstName",
|
||||
SecondName = "secondName",
|
||||
BirthDate = Now.AddYears(-10),
|
||||
Gender = PatientEnum.Gender.Female,
|
||||
Ids = new Dictionary<string, string> { { "MR", "123456" }, { "VN", "654321" } }
|
||||
};
|
||||
|
||||
var testPatientAppointment = new PatientAppointment
|
||||
{
|
||||
PatientId = PatientId,
|
||||
Patient = patient,
|
||||
CreateTime = Now.AddHours(-2),
|
||||
UpdateTime = Now.AddHours(-2)
|
||||
};
|
||||
|
||||
var testPatientAppointment2 = new PatientAppointment
|
||||
{
|
||||
PatientId = PatientId,
|
||||
Patient = patient,
|
||||
CreateTime = Now.AddHours(-3),
|
||||
UpdateTime = Now.AddHours(-3),
|
||||
VisitNumber = "654321",
|
||||
AppointmentReason = "appointmentReason",
|
||||
ResourceGroups =
|
||||
[
|
||||
new PatientAppointmentResourceGroup
|
||||
{
|
||||
Locations = [new PatientLocation("UCI5C", "Box4")]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("patients_appointments");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("patients_appointments");
|
||||
|
||||
_repository = new AppointmentRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(testPatientAppointment);
|
||||
await _repository.InsertOneAsync(testPatientAppointment2);
|
||||
}
|
||||
|
||||
private AppointmentRepository _repository;
|
||||
|
||||
@@ -72,77 +75,102 @@ public class AppointmentRepositoryTest
|
||||
private static readonly DateTime Now = DateTime.Now;
|
||||
private static readonly ObjectId PatientId = ObjectId.GenerateNewId();
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="AppointmentRepository"/>.GetByPatient returns a non-null, non-empty list when a valid patient identifier is provided.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetByPatient_Find_Patient_Return_List()
|
||||
{
|
||||
var result = await _repository.GetByPatient(PatientId);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Not.Empty);
|
||||
}
|
||||
public async Task GetByPatient_Find_Patient_Return_List()
|
||||
{
|
||||
var result = await _repository.GetByPatient(PatientId);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Not.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="AppointmentRepository.GetByPatient"/> returns a non-null, empty list when no records are found for the specified patient identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetByPatient_not_Find_Patient_Return_Empty_List()
|
||||
{
|
||||
var result = await _repository.GetByPatient(ObjectId.GenerateNewId());
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
public async Task GetByPatient_not_Find_Patient_Return_Empty_List()
|
||||
{
|
||||
var result = await _repository.GetByPatient(ObjectId.GenerateNewId());
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository returns <c>null</c> when no patient is found matching the specified patient identifier and visit number.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByPatientAndVisitNumber_Not_Find_Patient_Return_Null()
|
||||
{
|
||||
var result = await _repository.FindByPatientAndVisitNumber(PatientId, "visitNumber");
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
public async Task FindByPatientAndVisitNumber_Not_Find_Patient_Return_Null()
|
||||
{
|
||||
var result = await _repository.FindByPatientAndVisitNumber(PatientId, "visitNumber");
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's FindByPatientAndVisitNumber method successfully retrieves
|
||||
/// the corresponding appointment when a valid patient identifier and an existing visit number are supplied.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByPatientAndVisitNumber_Find_Patient_Return_Appointment()
|
||||
{
|
||||
var result = await _repository.FindByPatientAndVisitNumber(PatientId, "654321");
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result!.VisitNumber, Is.EqualTo("654321"));
|
||||
}
|
||||
public async Task FindByPatientAndVisitNumber_Find_Patient_Return_Appointment()
|
||||
{
|
||||
var result = await _repository.FindByPatientAndVisitNumber(PatientId, "654321");
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result!.VisitNumber, Is.EqualTo("654321"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository returns null when searching for an appointment by patient ID and a reason that does not match any existing appointment.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByPatientAndReason_Not_Find_Patient_Return_Null()
|
||||
{
|
||||
var result = await _repository.FindByPatientAndReason(PatientId, "NotappointmentReason");
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
public async Task FindByPatientAndReason_Not_Find_Patient_Return_Null()
|
||||
{
|
||||
var result = await _repository.FindByPatientAndReason(PatientId, "NotappointmentReason");
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that FindByPatientAndReason returns a non-null appointment containing the expected AppointmentReason for the specified patient.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByPatientAndReason_Find_Patient_Return_Appointment()
|
||||
{
|
||||
var result = await _repository.FindByPatientAndReason(PatientId, "appointmentReason");
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result!.AppointmentReason, Is.EqualTo("appointmentReason"));
|
||||
}
|
||||
public async Task FindByPatientAndReason_Find_Patient_Return_Appointment()
|
||||
{
|
||||
var result = await _repository.FindByPatientAndReason(PatientId, "appointmentReason");
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result!.AppointmentReason, Is.EqualTo("appointmentReason"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="AppointmentRepository"/>.<c>FindByLocation</c> returns an empty (non-null) collection when no patient is associated with the specified location.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByLocation_Not_Find_Patient_Return_Null()
|
||||
{
|
||||
var location = new PatientLocation("UCI5C", "Box3");
|
||||
|
||||
var result = await _repository.FindByLocation(location);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Count(), Is.EqualTo(0));
|
||||
}
|
||||
public async Task FindByLocation_Not_Find_Patient_Return_Null()
|
||||
{
|
||||
var location = new PatientLocation("UCI5C", "Box3");
|
||||
|
||||
var result = await _repository.FindByLocation(location);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Count(), Is.EqualTo(0));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="AppointmentRepository.FindByLocation"/> successfully retrieves the appointment associated with a patient located at the specified <see cref="PatientLocation"/>.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByLocation_Find_Patient_Return_Appointment()
|
||||
{
|
||||
var location = new PatientLocation("UCI5C", "Box4");
|
||||
|
||||
var result = await _repository.FindByLocation(location);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Count(), Is.EqualTo(1));
|
||||
}
|
||||
public async Task FindByLocation_Find_Patient_Return_Appointment()
|
||||
{
|
||||
var location = new PatientLocation("UCI5C", "Box4");
|
||||
|
||||
var result = await _repository.FindByLocation(location);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Count(), Is.EqualTo(1));
|
||||
}
|
||||
}
|
||||
@@ -13,86 +13,93 @@ namespace adas_core.Test.Repositories;
|
||||
[Category("Integration")]
|
||||
public class ConfigObservationRepositoryTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the integration test environment by recreating the "config_observations" MongoDB
|
||||
/// collection and seeding it with sample <see cref="ConfigObservation"/> records that cover
|
||||
/// different configuration scenarios, including coded and uncoded observations, parent coding
|
||||
/// system references, original name mappings, and observations with min/max alert thresholds
|
||||
/// and forced alert behavior.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
_id = ObjectId.GenerateNewId();
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
_masterListMock = new Mock<IMasterListServiceFactory>();
|
||||
|
||||
var testConfigObservation = new List<ConfigObservation>
|
||||
public async Task Init()
|
||||
{
|
||||
new()
|
||||
_id = ObjectId.GenerateNewId();
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
_masterListMock = new Mock<IMasterListServiceFactory>();
|
||||
|
||||
var testConfigObservation = new List<ConfigObservation>
|
||||
{
|
||||
Id = _id,
|
||||
Name = "Hemoglobina",
|
||||
Code = "12345",
|
||||
CodingSystem = "SNM"
|
||||
},
|
||||
|
||||
new()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Name = "Glucemia",
|
||||
Code = "54321",
|
||||
CodingSystem = "SNM",
|
||||
OriginalName = "GLU"
|
||||
},
|
||||
|
||||
new()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Name = "Sodio",
|
||||
OriginalName = "Sodio"
|
||||
},
|
||||
|
||||
new()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Name = "ph",
|
||||
Code = "555",
|
||||
CodingSystem = "MG4",
|
||||
ParentCode = "3333",
|
||||
ParentCodingSystem = "SNM"
|
||||
},
|
||||
|
||||
|
||||
new()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Name = "SOFA",
|
||||
Code = "278061009",
|
||||
OriginalName = "SOFA",
|
||||
CodingSystem = "SNM",
|
||||
MinAlert = 10,
|
||||
MinWarn = 14
|
||||
},
|
||||
|
||||
|
||||
new()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Name = "FC",
|
||||
Code = "147842",
|
||||
//originalName = "MDC_ECG_CARD_BEAT_RATE",
|
||||
CodingSystem = "MDC",
|
||||
ParentCode = "69965",
|
||||
ParentName = "MDC_DEV_MON_PHYSIO_MULTI_PARAM_MDS",
|
||||
MinAlert = 60,
|
||||
MaxAlert = 100,
|
||||
ForceAlert = true
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("config_observations");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("config_observations");
|
||||
|
||||
_repository =
|
||||
new ConfigObservationRepository(_optionsApiSettings, IntegrationDb.Database, _masterListMock.Object);
|
||||
|
||||
await _repository.InsertManyAsync(testConfigObservation);
|
||||
}
|
||||
new()
|
||||
{
|
||||
Id = _id,
|
||||
Name = "Hemoglobina",
|
||||
Code = "12345",
|
||||
CodingSystem = "SNM"
|
||||
},
|
||||
|
||||
new()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Name = "Glucemia",
|
||||
Code = "54321",
|
||||
CodingSystem = "SNM",
|
||||
OriginalName = "GLU"
|
||||
},
|
||||
|
||||
new()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Name = "Sodio",
|
||||
OriginalName = "Sodio"
|
||||
},
|
||||
|
||||
new()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Name = "ph",
|
||||
Code = "555",
|
||||
CodingSystem = "MG4",
|
||||
ParentCode = "3333",
|
||||
ParentCodingSystem = "SNM"
|
||||
},
|
||||
|
||||
|
||||
new()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Name = "SOFA",
|
||||
Code = "278061009",
|
||||
OriginalName = "SOFA",
|
||||
CodingSystem = "SNM",
|
||||
MinAlert = 10,
|
||||
MinWarn = 14
|
||||
},
|
||||
|
||||
|
||||
new()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Name = "FC",
|
||||
Code = "147842",
|
||||
//originalName = "MDC_ECG_CARD_BEAT_RATE",
|
||||
CodingSystem = "MDC",
|
||||
ParentCode = "69965",
|
||||
ParentName = "MDC_DEV_MON_PHYSIO_MULTI_PARAM_MDS",
|
||||
MinAlert = 60,
|
||||
MaxAlert = 100,
|
||||
ForceAlert = true
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("config_observations");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("config_observations");
|
||||
|
||||
_repository =
|
||||
new ConfigObservationRepository(_optionsApiSettings, IntegrationDb.Database, _masterListMock.Object);
|
||||
|
||||
await _repository.InsertManyAsync(testConfigObservation);
|
||||
}
|
||||
|
||||
private ConfigObservationRepository _repository;
|
||||
private IMock<IMasterListServiceFactory> _masterListMock;
|
||||
@@ -106,85 +113,101 @@ public class ConfigObservationRepositoryTest
|
||||
private IOptions<ApiSettings> _optionsApiSettings;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's FindById method returns a non-null configuration result when queried with a valid id.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindById_Find_Id_Return_Configs()
|
||||
{
|
||||
var result = await _repository.FindById(_id);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task FindById_Not_Find_Id_Return_Empty()
|
||||
{
|
||||
var result = await _repository.FindById(ObjectId.GenerateNewId());
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Update_Find_Id_Return_Update_Configs()
|
||||
{
|
||||
var updateConfigObservation = new ConfigObservation
|
||||
public async Task FindById_Find_Id_Return_Configs()
|
||||
{
|
||||
Id = _id,
|
||||
Name = "Hemoglobina 2",
|
||||
Code = "12345",
|
||||
CodingSystem = "SNM"
|
||||
};
|
||||
|
||||
var result = await _repository.FindById(_id);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Name, Is.EqualTo("Hemoglobina"));
|
||||
|
||||
var resultUpdate = await _repository.Update(updateConfigObservation);
|
||||
|
||||
Assert.That(resultUpdate, Is.Not.Null);
|
||||
Assert.That(resultUpdate.Name, Is.EqualTo("Hemoglobina 2"));
|
||||
}
|
||||
var result = await _repository.FindById(_id);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the <c>FindById</c> repository method returns <c>null</c> when invoked with a newly generated, non-existing identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Update_Not_Find_Id_Create_It()
|
||||
{
|
||||
var id2 = ObjectId.GenerateNewId();
|
||||
var updateConfigObservation = new ConfigObservation
|
||||
public async Task FindById_Not_Find_Id_Return_Empty()
|
||||
{
|
||||
Id = id2,
|
||||
Name = "Hemoglobina",
|
||||
Code = "12345",
|
||||
CodingSystem = "SNM"
|
||||
};
|
||||
|
||||
await _repository.Update(updateConfigObservation);
|
||||
var resultfind = await _repository.FindById(id2);
|
||||
Assert.That(resultfind, Is.Not.Null);
|
||||
}
|
||||
|
||||
var result = await _repository.FindById(ObjectId.GenerateNewId());
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that an existing <see cref="ConfigObservation"/> can be retrieved by its identifier and subsequently updated, ensuring the updated entity reflects the new values.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Delete_With_Base_DeleteAsync()
|
||||
{
|
||||
var iid = ObjectId.GenerateNewId();
|
||||
var deleteConfigObservation = new ConfigObservation
|
||||
public async Task Update_Find_Id_Return_Update_Configs()
|
||||
{
|
||||
Id = iid,
|
||||
Name = "Hemoglobina3",
|
||||
Code = "123455",
|
||||
CodingSystem = "SNMM"
|
||||
};
|
||||
var updateConfigObservation = new ConfigObservation
|
||||
{
|
||||
Id = _id,
|
||||
Name = "Hemoglobina 2",
|
||||
Code = "12345",
|
||||
CodingSystem = "SNM"
|
||||
};
|
||||
|
||||
var result = await _repository.FindById(_id);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Name, Is.EqualTo("Hemoglobina"));
|
||||
|
||||
var resultUpdate = await _repository.Update(updateConfigObservation);
|
||||
|
||||
Assert.That(resultUpdate, Is.Not.Null);
|
||||
Assert.That(resultUpdate.Name, Is.EqualTo("Hemoglobina 2"));
|
||||
}
|
||||
|
||||
var result = await _repository.FindById(iid);
|
||||
Assert.That(result, Is.Null);
|
||||
/// <summary>
|
||||
/// Verifies that the repository's Update operation creates a new record when the provided identifier does not exist in the data store, instead of failing.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Update_Not_Find_Id_Create_It()
|
||||
{
|
||||
var id2 = ObjectId.GenerateNewId();
|
||||
var updateConfigObservation = new ConfigObservation
|
||||
{
|
||||
Id = id2,
|
||||
Name = "Hemoglobina",
|
||||
Code = "12345",
|
||||
CodingSystem = "SNM"
|
||||
};
|
||||
|
||||
await _repository.Update(updateConfigObservation);
|
||||
var resultfind = await _repository.FindById(id2);
|
||||
Assert.That(resultfind, Is.Not.Null);
|
||||
}
|
||||
|
||||
await _repository.InsertOneAsync(deleteConfigObservation);
|
||||
|
||||
var resultInsert = await _repository.FindById(iid);
|
||||
Assert.That(resultInsert, Is.Not.Null);
|
||||
|
||||
await _repository.Delete(iid);
|
||||
|
||||
var resultDelete = await _repository.FindById(iid);
|
||||
Assert.That(resultDelete, Is.Null);
|
||||
}
|
||||
/// <summary>
|
||||
/// Verifies that the base delete operation removes a <see cref="ConfigObservation"/> from the repository.
|
||||
/// The test confirms the entity is absent before insertion, present after insertion, and absent again after deletion.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Delete_With_Base_DeleteAsync()
|
||||
{
|
||||
var iid = ObjectId.GenerateNewId();
|
||||
var deleteConfigObservation = new ConfigObservation
|
||||
{
|
||||
Id = iid,
|
||||
Name = "Hemoglobina3",
|
||||
Code = "123455",
|
||||
CodingSystem = "SNMM"
|
||||
};
|
||||
|
||||
var result = await _repository.FindById(iid);
|
||||
Assert.That(result, Is.Null);
|
||||
|
||||
await _repository.InsertOneAsync(deleteConfigObservation);
|
||||
|
||||
var resultInsert = await _repository.FindById(iid);
|
||||
Assert.That(resultInsert, Is.Not.Null);
|
||||
|
||||
await _repository.Delete(iid);
|
||||
|
||||
var resultDelete = await _repository.FindById(iid);
|
||||
Assert.That(resultDelete, Is.Null);
|
||||
}
|
||||
}
|
||||
@@ -11,27 +11,30 @@ namespace adas_core.Test.Repositories;
|
||||
[Category("Integration")]
|
||||
public class ConfigPumpsRepositoryTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the integration test environment by recreating the config_pumps collection and inserting a single configuration pump containing two empty items for use by subsequent tests.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var configPumpItem1 = new ConfigPumpItem();
|
||||
var configPumpItem2 = new ConfigPumpItem();
|
||||
|
||||
var configPumps = new ConfigPumps
|
||||
public async Task Init()
|
||||
{
|
||||
Id = "PV1",
|
||||
Items = [configPumpItem1, configPumpItem2]
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("config_pumps");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("config_pumps");
|
||||
|
||||
_repository = new ConfigPumpsRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(configPumps);
|
||||
}
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var configPumpItem1 = new ConfigPumpItem();
|
||||
var configPumpItem2 = new ConfigPumpItem();
|
||||
|
||||
var configPumps = new ConfigPumps
|
||||
{
|
||||
Id = "PV1",
|
||||
Items = [configPumpItem1, configPumpItem2]
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("config_pumps");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("config_pumps");
|
||||
|
||||
_repository = new ConfigPumpsRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(configPumps);
|
||||
}
|
||||
|
||||
private ConfigPumpsRepository _repository;
|
||||
|
||||
@@ -43,46 +46,55 @@ public class ConfigPumpsRepositoryTest
|
||||
private IOptions<ApiSettings> _optionsApiSettings;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="ConfigPumpsRepository.FindById"/> returns a non-null result when searching by the identifier "PV1".
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindById_Find_id_Return_List()
|
||||
{
|
||||
var result = await _repository.FindById("PV1");
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task FindAsync_not_Find_id_Return_Empty_List()
|
||||
{
|
||||
var result = await _repository.FindById("PV2");
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Insert_PumpConfig_returns2()
|
||||
{
|
||||
var configPumpItem1 = new ConfigPumpItem();
|
||||
var configPumpItem2 = new ConfigPumpItem();
|
||||
|
||||
var newPumpConfig = new ConfigPumps
|
||||
public async Task FindById_Find_id_Return_List()
|
||||
{
|
||||
Id = "PV2",
|
||||
Items = [configPumpItem1, configPumpItem2]
|
||||
};
|
||||
var result = await _repository.FindById("PV1");
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
|
||||
await _repository.InsertOneAsync(newPumpConfig);
|
||||
/// <summary>
|
||||
/// Verifies that the repository's FindById method returns null when no entity is found for the specified identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindAsync_not_Find_id_Return_Empty_List()
|
||||
{
|
||||
var result = await _repository.FindById("PV2");
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
var result = await _repository.GetAllConfigs();
|
||||
|
||||
Assert.That(result, Has.Count.EqualTo(2));
|
||||
|
||||
var pumpCfgInserted = await _repository.FindById(newPumpConfig.Id);
|
||||
|
||||
Assert.That(pumpCfgInserted, Is.Not.EqualTo(null));
|
||||
|
||||
Debug.Assert(pumpCfgInserted != null, nameof(pumpCfgInserted) + " != null");
|
||||
|
||||
await _repository.DeleteConfig(pumpCfgInserted);
|
||||
}
|
||||
/// <summary>
|
||||
/// Tests that inserting a new pump configuration with two items increases the total configuration count to two, that the inserted configuration can be retrieved by its identifier, and that the inserted configuration can be successfully deleted.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Insert_PumpConfig_returns2()
|
||||
{
|
||||
var configPumpItem1 = new ConfigPumpItem();
|
||||
var configPumpItem2 = new ConfigPumpItem();
|
||||
|
||||
var newPumpConfig = new ConfigPumps
|
||||
{
|
||||
Id = "PV2",
|
||||
Items = [configPumpItem1, configPumpItem2]
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(newPumpConfig);
|
||||
|
||||
var result = await _repository.GetAllConfigs();
|
||||
|
||||
Assert.That(result, Has.Count.EqualTo(2));
|
||||
|
||||
var pumpCfgInserted = await _repository.FindById(newPumpConfig.Id);
|
||||
|
||||
Assert.That(pumpCfgInserted, Is.Not.EqualTo(null));
|
||||
|
||||
Debug.Assert(pumpCfgInserted != null, nameof(pumpCfgInserted) + " != null");
|
||||
|
||||
await _repository.DeleteConfig(pumpCfgInserted);
|
||||
}
|
||||
}
|
||||
@@ -10,27 +10,30 @@ namespace adas_core.Test.Repositories;
|
||||
[Category("Integration")]
|
||||
public class ConfigUnitsRepositoryTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Performs one-time setup for integration tests by resetting the <c>config_units</c> collection and seeding it with a single <see cref="ConfigUnits"/> document (Id "PV1") containing two empty <see cref="ConfigUnitItem"/> entries, then initializes the <see cref="ConfigUnitsRepository"/> used by the tests.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var configUnitItem1 = new ConfigUnitItem();
|
||||
var configUnitItem2 = new ConfigUnitItem();
|
||||
|
||||
var configUnits = new ConfigUnits
|
||||
public async Task Init()
|
||||
{
|
||||
Id = "PV1",
|
||||
Items = [configUnitItem1, configUnitItem2]
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("config_units");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("config_units");
|
||||
|
||||
_repository = new ConfigUnitsRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(configUnits);
|
||||
}
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var configUnitItem1 = new ConfigUnitItem();
|
||||
var configUnitItem2 = new ConfigUnitItem();
|
||||
|
||||
var configUnits = new ConfigUnits
|
||||
{
|
||||
Id = "PV1",
|
||||
Items = [configUnitItem1, configUnitItem2]
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("config_units");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("config_units");
|
||||
|
||||
_repository = new ConfigUnitsRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(configUnits);
|
||||
}
|
||||
|
||||
private ConfigUnitsRepository _repository;
|
||||
|
||||
@@ -42,19 +45,25 @@ public class ConfigUnitsRepositoryTest
|
||||
private IOptions<ApiSettings> _optionsApiSettings;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's <c>FindById</c> method returns a non-null result when searching by the identifier "PV1".
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindById_Find_id_Return_List()
|
||||
{
|
||||
var result = await _repository.FindById("PV1");
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
public async Task FindById_Find_id_Return_List()
|
||||
{
|
||||
var result = await _repository.FindById("PV1");
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="ConfigUnitsRepository.FindById"/> returns null when invoked with an identifier ("PV2") that does not exist in the repository.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindAsync_not_Find_id_Return_Empty_List()
|
||||
{
|
||||
var result = await _repository.FindById("PV2");
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
public async Task FindAsync_not_Find_id_Return_Empty_List()
|
||||
{
|
||||
var result = await _repository.FindById("PV2");
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
}
|
||||
@@ -12,47 +12,52 @@ namespace adas_core.Test.Repositories;
|
||||
[Category("Integration")]
|
||||
public class DiagnosisArchiveRepositoryTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the test fixture by creating sample patient diagnosis records, resetting the
|
||||
/// archive collection in the integration database, and configuring the diagnosis archive
|
||||
/// repository used by the test suite.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var patientDiagnosis1 = new PatientDiagnosis
|
||||
public async Task Init()
|
||||
{
|
||||
Id = Id,
|
||||
PatientId = PatientId,
|
||||
Time = Now.AddDays(-1),
|
||||
Code = "code1",
|
||||
DiagnosisSystem = "diagnosisSystem"
|
||||
};
|
||||
|
||||
var patientDiagnosis2 = new PatientDiagnosis
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = PatientId,
|
||||
Time = Now.AddDays(-2),
|
||||
Code = "code2",
|
||||
DiagnosisSystem = "diagnosisSystem"
|
||||
};
|
||||
|
||||
var patientDiagnosis3 = new PatientDiagnosis
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = PatientId,
|
||||
Time = Now.AddDays(-3),
|
||||
Code = "code3",
|
||||
DiagnosisSystem = "diagnosisSystem"
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("archive_patients_diagnosis");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("archive_patients_diagnosis");
|
||||
|
||||
_repository = new DiagnosisArchiveRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(patientDiagnosis1);
|
||||
await _repository.InsertOneAsync(patientDiagnosis2);
|
||||
await _repository.InsertOneAsync(patientDiagnosis3);
|
||||
}
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var patientDiagnosis1 = new PatientDiagnosis
|
||||
{
|
||||
Id = Id,
|
||||
PatientId = PatientId,
|
||||
Time = Now.AddDays(-1),
|
||||
Code = "code1",
|
||||
DiagnosisSystem = "diagnosisSystem"
|
||||
};
|
||||
|
||||
var patientDiagnosis2 = new PatientDiagnosis
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = PatientId,
|
||||
Time = Now.AddDays(-2),
|
||||
Code = "code2",
|
||||
DiagnosisSystem = "diagnosisSystem"
|
||||
};
|
||||
|
||||
var patientDiagnosis3 = new PatientDiagnosis
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = PatientId,
|
||||
Time = Now.AddDays(-3),
|
||||
Code = "code3",
|
||||
DiagnosisSystem = "diagnosisSystem"
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("archive_patients_diagnosis");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("archive_patients_diagnosis");
|
||||
|
||||
_repository = new DiagnosisArchiveRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(patientDiagnosis1);
|
||||
await _repository.InsertOneAsync(patientDiagnosis2);
|
||||
await _repository.InsertOneAsync(patientDiagnosis3);
|
||||
}
|
||||
|
||||
private DiagnosisArchiveRepository _repository;
|
||||
|
||||
@@ -68,19 +73,24 @@ public class DiagnosisArchiveRepositoryTest
|
||||
private static readonly ObjectId Id = ObjectId.GenerateNewId();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's <c>DeleteBeforeDate</c> operation correctly removes all records
|
||||
/// for a given patient that were created before the specified cutoff date, while preserving records
|
||||
/// created on or after that date.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task DeleteBeforeDate()
|
||||
{
|
||||
var result = await _repository.Collection.FindAsync(p => p.PatientId == PatientId);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.ToList(), Has.Count.GreaterThan(1));
|
||||
|
||||
await _repository.DeleteBeforeDate(Now.AddDays(-1));
|
||||
|
||||
var resultDelete = await _repository.Collection.FindAsync(p => p.PatientId == PatientId);
|
||||
|
||||
Assert.That(resultDelete, Is.Not.Null);
|
||||
Assert.That(resultDelete.ToList(), Has.Count.EqualTo(1));
|
||||
}
|
||||
public async Task DeleteBeforeDate()
|
||||
{
|
||||
var result = await _repository.Collection.FindAsync(p => p.PatientId == PatientId);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.ToList(), Has.Count.GreaterThan(1));
|
||||
|
||||
await _repository.DeleteBeforeDate(Now.AddDays(-1));
|
||||
|
||||
var resultDelete = await _repository.Collection.FindAsync(p => p.PatientId == PatientId);
|
||||
|
||||
Assert.That(resultDelete, Is.Not.Null);
|
||||
Assert.That(resultDelete.ToList(), Has.Count.EqualTo(1));
|
||||
}
|
||||
}
|
||||
@@ -12,47 +12,50 @@ namespace adas_core.Test.Repositories;
|
||||
[Category("Integration")]
|
||||
public class DiagnosisRepositoryTest
|
||||
{
|
||||
/// <summary>
|
||||
/// One-time test setup that prepares the integration database for patient diagnosis tests by dropping and recreating the diagnoses collection, inserting three sample <see cref="PatientDiagnosis"/> records (one with predefined test identifiers and two with auto-generated identifiers), and initializing the <see cref="DiagnosisRepository"/> under test.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var patientDiagnosis1 = new PatientDiagnosis
|
||||
public async Task Init()
|
||||
{
|
||||
Id = Id,
|
||||
PatientId = PatientId,
|
||||
Time = Now,
|
||||
Code = "code1",
|
||||
DiagnosisSystem = "diagnosisSystem"
|
||||
};
|
||||
|
||||
var patientDiagnosis2 = new PatientDiagnosis
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
Time = Now,
|
||||
Code = "code2",
|
||||
DiagnosisSystem = "diagnosisSystem"
|
||||
};
|
||||
|
||||
var patientDiagnosis3 = new PatientDiagnosis
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
Time = Now,
|
||||
Code = "code3",
|
||||
DiagnosisSystem = "diagnosisSystem"
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("patients_diagnosis");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("patients_diagnosis");
|
||||
|
||||
_repository = new DiagnosisRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(patientDiagnosis1);
|
||||
await _repository.InsertOneAsync(patientDiagnosis2);
|
||||
await _repository.InsertOneAsync(patientDiagnosis3);
|
||||
}
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var patientDiagnosis1 = new PatientDiagnosis
|
||||
{
|
||||
Id = Id,
|
||||
PatientId = PatientId,
|
||||
Time = Now,
|
||||
Code = "code1",
|
||||
DiagnosisSystem = "diagnosisSystem"
|
||||
};
|
||||
|
||||
var patientDiagnosis2 = new PatientDiagnosis
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
Time = Now,
|
||||
Code = "code2",
|
||||
DiagnosisSystem = "diagnosisSystem"
|
||||
};
|
||||
|
||||
var patientDiagnosis3 = new PatientDiagnosis
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
Time = Now,
|
||||
Code = "code3",
|
||||
DiagnosisSystem = "diagnosisSystem"
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("patients_diagnosis");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("patients_diagnosis");
|
||||
|
||||
_repository = new DiagnosisRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(patientDiagnosis1);
|
||||
await _repository.InsertOneAsync(patientDiagnosis2);
|
||||
await _repository.InsertOneAsync(patientDiagnosis3);
|
||||
}
|
||||
|
||||
private DiagnosisRepository _repository;
|
||||
|
||||
@@ -68,130 +71,162 @@ public class DiagnosisRepositoryTest
|
||||
private static readonly ObjectId Id = ObjectId.GenerateNewId();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository returns a non-null and non-empty collection when retrieving records for an existing patient.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetByPatient_Find_Patient_Return_List()
|
||||
{
|
||||
var result = await _repository.GetByPatient(PatientId);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Not.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetByPatient_not_Find_Patient_Return_Empty_List()
|
||||
{
|
||||
var result = await _repository.GetByPatient(ObjectId.GenerateNewId());
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task FindByPatientIdAndCode_Find_Patient_Return_Diagnois()
|
||||
{
|
||||
var result = await _repository.FindByPatientIdAndCode(PatientId, "code1", "diagnosisSystem");
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task FindByPatientIdAndCode_not_Find_Patient_Return_null()
|
||||
{
|
||||
var result = await _repository.FindByPatientIdAndCode(ObjectId.GenerateNewId(), "code4", "diagnosisSystem");
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task FindByPatientIdAsync_Find_Patient_Return_List()
|
||||
{
|
||||
var result = await _repository.FindByPatientIdAsync(PatientId);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.ToList(), Is.Not.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task FindByPatientIdAsync_not_Find_Patient_Return_Empty_List()
|
||||
{
|
||||
var result = await _repository.FindByPatientIdAsync(ObjectId.GenerateNewId());
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.ToList(), Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task DeleteAsync_Find_id()
|
||||
{
|
||||
var patientDiagnosis = new PatientDiagnosis
|
||||
public async Task GetByPatient_Find_Patient_Return_List()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
Time = Now,
|
||||
Code = "code1",
|
||||
DiagnosisSystem = "diagnosisSystem"
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(patientDiagnosis);
|
||||
|
||||
var result = await _repository.FindByPatientIdAsync(patientDiagnosis.PatientId);
|
||||
Assert.That(result.ToList(), Has.Count.EqualTo(1));
|
||||
|
||||
await _repository.DeleteAsync(patientDiagnosis.Id);
|
||||
|
||||
var resultDelete = await _repository.FindByPatientIdAsync(patientDiagnosis.PatientId);
|
||||
Assert.That(resultDelete.ToList(), Is.Empty);
|
||||
}
|
||||
var result = await _repository.GetByPatient(PatientId);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Not.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="DiagnosisRepository.GetByPatient"/> returns an empty list when no records are found for the specified patient identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task DeleteByPatientId_Find_patientId()
|
||||
{
|
||||
var patientDiagnosis = new PatientDiagnosis
|
||||
public async Task GetByPatient_not_Find_Patient_Return_Empty_List()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
Time = Now,
|
||||
Code = "code1",
|
||||
DiagnosisSystem = "diagnosisSystem"
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(patientDiagnosis);
|
||||
|
||||
var result = await _repository.FindByPatientIdAsync(patientDiagnosis.PatientId);
|
||||
Assert.That(result.ToList(), Has.Count.EqualTo(1));
|
||||
|
||||
await _repository.DeleteByPatientId(patientDiagnosis.PatientId);
|
||||
|
||||
var resultDelete = await _repository.FindByPatientIdAsync(patientDiagnosis.PatientId);
|
||||
Assert.That(resultDelete.ToList(), Is.Empty);
|
||||
}
|
||||
var result = await _repository.GetByPatient(ObjectId.GenerateNewId());
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="DiagnosisRepository.FindByPatientIdAndCode"/> successfully retrieves a diagnosis for an existing patient using the provided patient identifier, diagnosis code, and diagnosis system.
|
||||
/// </summary>
|
||||
/// <returns>A task that represents the asynchronous test execution.</returns>
|
||||
[Test]
|
||||
public async Task UpdateManyObjectId_With_base_UpdateManyObjectIdAsync()
|
||||
{
|
||||
var patientDiagnosis = new PatientDiagnosis
|
||||
public async Task FindByPatientIdAndCode_Find_Patient_Return_Diagnois()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
Time = Now,
|
||||
Code = "code1",
|
||||
DiagnosisSystem = "diagnosisSystem"
|
||||
};
|
||||
var result = await _repository.FindByPatientIdAndCode(PatientId, "code1", "diagnosisSystem");
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
|
||||
await _repository.InsertOneAsync(patientDiagnosis);
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="DiagnosisRepository.FindByPatientIdAndCode"/> returns <c>null</c> when no patient is found
|
||||
/// for the provided patient identifier, code, and diagnosis system.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByPatientIdAndCode_not_Find_Patient_Return_null()
|
||||
{
|
||||
var result = await _repository.FindByPatientIdAndCode(ObjectId.GenerateNewId(), "code4", "diagnosisSystem");
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
var resultInsert = await _repository.FindByPatientIdAsync(patientDiagnosis.PatientId);
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="DiagnosisRepository.FindByPatientIdAsync"/> returns a non-null, non-empty list when looking up an existing patient by their identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByPatientIdAsync_Find_Patient_Return_List()
|
||||
{
|
||||
var result = await _repository.FindByPatientIdAsync(PatientId);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.ToList(), Is.Not.Empty);
|
||||
}
|
||||
|
||||
var resultList = resultInsert.ToList();
|
||||
/// <summary>
|
||||
/// Verifies that <c>FindByPatientIdAsync</c> returns a non-null empty list when no patient matches the provided patient ID.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByPatientIdAsync_not_Find_Patient_Return_Empty_List()
|
||||
{
|
||||
var result = await _repository.FindByPatientIdAsync(ObjectId.GenerateNewId());
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.ToList(), Is.Empty);
|
||||
}
|
||||
|
||||
Assert.That(resultList, Has.Count.EqualTo(1));
|
||||
/// <summary>
|
||||
/// Verifies that <c>DeleteAsync</c> removes a patient diagnosis record by its identifier: after insertion, the record is retrievable by patient id, and once deleted, the search by patient id returns no results.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task DeleteAsync_Find_id()
|
||||
{
|
||||
var patientDiagnosis = new PatientDiagnosis
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
Time = Now,
|
||||
Code = "code1",
|
||||
DiagnosisSystem = "diagnosisSystem"
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(patientDiagnosis);
|
||||
|
||||
var result = await _repository.FindByPatientIdAsync(patientDiagnosis.PatientId);
|
||||
Assert.That(result.ToList(), Has.Count.EqualTo(1));
|
||||
|
||||
await _repository.DeleteAsync(patientDiagnosis.Id);
|
||||
|
||||
var resultDelete = await _repository.FindByPatientIdAsync(patientDiagnosis.PatientId);
|
||||
Assert.That(resultDelete.ToList(), Is.Empty);
|
||||
}
|
||||
|
||||
var newPatientId = ObjectId.GenerateNewId();
|
||||
/// <summary>
|
||||
/// Verifies that <c>DeleteByPatientId</c> removes all diagnoses associated with the specified patient
|
||||
/// by inserting a diagnosis, confirming it can be found, deleting it by patient id, and then
|
||||
/// asserting that no diagnoses remain for that patient.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task DeleteByPatientId_Find_patientId()
|
||||
{
|
||||
var patientDiagnosis = new PatientDiagnosis
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
Time = Now,
|
||||
Code = "code1",
|
||||
DiagnosisSystem = "diagnosisSystem"
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(patientDiagnosis);
|
||||
|
||||
var result = await _repository.FindByPatientIdAsync(patientDiagnosis.PatientId);
|
||||
Assert.That(result.ToList(), Has.Count.EqualTo(1));
|
||||
|
||||
await _repository.DeleteByPatientId(patientDiagnosis.PatientId);
|
||||
|
||||
var resultDelete = await _repository.FindByPatientIdAsync(patientDiagnosis.PatientId);
|
||||
Assert.That(resultDelete.ToList(), Is.Empty);
|
||||
}
|
||||
|
||||
await _repository.UpdateManyObjectId("patientId", newPatientId, patientDiagnosis.PatientId);
|
||||
|
||||
var resultUpdate = await _repository.FindByPatientIdAsync(newPatientId);
|
||||
Assert.That(resultUpdate, Is.Not.Null);
|
||||
Assert.That(resultUpdate.ToList().Count(f => f.PatientId == newPatientId), Is.EqualTo(1));
|
||||
}
|
||||
/// <summary>
|
||||
/// Tests that <c>UpdateManyObjectId</c> correctly updates the <c>PatientId</c> field across all matching <see cref="PatientDiagnosis"/> documents by replacing the original ObjectId with a new one.
|
||||
/// Verifies that after the update, the document can be retrieved using the new patient identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task UpdateManyObjectId_With_base_UpdateManyObjectIdAsync()
|
||||
{
|
||||
var patientDiagnosis = new PatientDiagnosis
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
Time = Now,
|
||||
Code = "code1",
|
||||
DiagnosisSystem = "diagnosisSystem"
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(patientDiagnosis);
|
||||
|
||||
var resultInsert = await _repository.FindByPatientIdAsync(patientDiagnosis.PatientId);
|
||||
|
||||
var resultList = resultInsert.ToList();
|
||||
|
||||
Assert.That(resultList, Has.Count.EqualTo(1));
|
||||
|
||||
var newPatientId = ObjectId.GenerateNewId();
|
||||
|
||||
await _repository.UpdateManyObjectId("patientId", newPatientId, patientDiagnosis.PatientId);
|
||||
|
||||
var resultUpdate = await _repository.FindByPatientIdAsync(newPatientId);
|
||||
Assert.That(resultUpdate, Is.Not.Null);
|
||||
Assert.That(resultUpdate.ToList().Count(f => f.PatientId == newPatientId), Is.EqualTo(1));
|
||||
}
|
||||
}
|
||||
@@ -13,69 +13,82 @@ namespace adas_core.Test.Repositories;
|
||||
[Category("Integration")]
|
||||
public class DischargeRepositoryTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Performs one-time test setup for discharge integration tests by initializing API settings, dropping and recreating the "discharge" collection in the integration database, and instantiating the <see cref="DischargeRepository"/>.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
// Initialize options and repository
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("discharge");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("discharge");
|
||||
|
||||
_dischargeRepository = new DischargeRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
}
|
||||
public async Task Init()
|
||||
{
|
||||
// Initialize options and repository
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("discharge");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("discharge");
|
||||
|
||||
_dischargeRepository = new DischargeRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
}
|
||||
|
||||
private DischargeRepository _dischargeRepository;
|
||||
private readonly ApiSettings _apiSettings = new();
|
||||
private IOptions<ApiSettings> _optionsApiSettings;
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>InsertOneAsync</c> successfully persists a discharge document and that the
|
||||
/// inserted record can be retrieved by its identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task InsertOneAsync_ShouldInsertDischarge()
|
||||
{
|
||||
// Arrange
|
||||
var discharge = TestUtilities.CreateValidDischarge();
|
||||
|
||||
// Act
|
||||
await _dischargeRepository.InsertOneAsync(discharge);
|
||||
|
||||
var result = await _dischargeRepository.FindById(discharge.Id);
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
public async Task InsertOneAsync_ShouldInsertDischarge()
|
||||
{
|
||||
// Arrange
|
||||
var discharge = TestUtilities.CreateValidDischarge();
|
||||
|
||||
// Act
|
||||
await _dischargeRepository.InsertOneAsync(discharge);
|
||||
|
||||
var result = await _dischargeRepository.FindById(discharge.Id);
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the <c>Delete</c> repository operation removes a discharge so that subsequent lookups by its identifier return no result.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Delete_ShouldDeleteDischarge()
|
||||
{
|
||||
// Arrange
|
||||
var discharge = TestUtilities.CreateValidDischarge();
|
||||
await _dischargeRepository.InsertOneAsync(discharge);
|
||||
|
||||
// Act
|
||||
await _dischargeRepository.Delete(discharge.Id);
|
||||
|
||||
var result = await _dischargeRepository.FindById(discharge.Id);
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
public async Task Delete_ShouldDeleteDischarge()
|
||||
{
|
||||
// Arrange
|
||||
var discharge = TestUtilities.CreateValidDischarge();
|
||||
await _dischargeRepository.InsertOneAsync(discharge);
|
||||
|
||||
// Act
|
||||
await _dischargeRepository.Delete(discharge.Id);
|
||||
|
||||
var result = await _dischargeRepository.FindById(discharge.Id);
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that an existing discharge record is successfully updated in the repository with new field values.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Update_DischargeSuccessfullyUpdated()
|
||||
{
|
||||
// Arrange
|
||||
var pocId = new ObjectId();
|
||||
var discharge = TestUtilities.CreateValidDischarge();
|
||||
discharge.PointOfCareId = pocId;
|
||||
await _dischargeRepository.InsertOneAsync(discharge);
|
||||
|
||||
// Act
|
||||
discharge.Service = "UpdatedService";
|
||||
await _dischargeRepository.Update(discharge);
|
||||
|
||||
// Retrieve the discharge from the database
|
||||
var updatedDischarge = await _dischargeRepository.GetDischargeByPointOfCareId(pocId);
|
||||
|
||||
// Assert
|
||||
Assert.That(updatedDischarge, Is.Not.Null);
|
||||
Assert.That(updatedDischarge?.Service, Is.EqualTo("UpdatedService"));
|
||||
}
|
||||
public async Task Update_DischargeSuccessfullyUpdated()
|
||||
{
|
||||
// Arrange
|
||||
var pocId = new ObjectId();
|
||||
var discharge = TestUtilities.CreateValidDischarge();
|
||||
discharge.PointOfCareId = pocId;
|
||||
await _dischargeRepository.InsertOneAsync(discharge);
|
||||
|
||||
// Act
|
||||
discharge.Service = "UpdatedService";
|
||||
await _dischargeRepository.Update(discharge);
|
||||
|
||||
// Retrieve the discharge from the database
|
||||
var updatedDischarge = await _dischargeRepository.GetDischargeByPointOfCareId(pocId);
|
||||
|
||||
// Assert
|
||||
Assert.That(updatedDischarge, Is.Not.Null);
|
||||
Assert.That(updatedDischarge?.Service, Is.EqualTo("UpdatedService"));
|
||||
}
|
||||
|
||||
// [Test]
|
||||
// public async Task UpdateUnit_UnitNameSuccessfullyUpdated()
|
||||
@@ -119,50 +132,59 @@ public class DischargeRepositoryTest
|
||||
// Assert.That(updatedDischarge?.Patient?.Id, Is.EqualTo(updatedPatient.Id));
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's <c>FindAll</c> method returns all discharge records previously inserted via <c>InsertManyAsync</c>, returning a non-null, non-empty collection whose count matches the number of inserted records.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindAll_ReturnsAllDischarges()
|
||||
{
|
||||
// Arrange: Prepare test data
|
||||
var expectedDischarges = new List<Discharge>
|
||||
public async Task FindAll_ReturnsAllDischarges()
|
||||
{
|
||||
new() { Id = ObjectId.GenerateNewId(), DischargeDate = DateTime.UtcNow },
|
||||
new() { Id = ObjectId.GenerateNewId(), DischargeDate = DateTime.UtcNow },
|
||||
new() { Id = ObjectId.GenerateNewId(), DischargeDate = DateTime.UtcNow }
|
||||
};
|
||||
|
||||
await _dischargeRepository.InsertManyAsync(expectedDischarges);
|
||||
|
||||
// Act: Call the method under test
|
||||
var actualDischarges = await _dischargeRepository.FindAll();
|
||||
|
||||
var discharges = actualDischarges.ToList();
|
||||
Assert.That(discharges, Is.Not.Null);
|
||||
Assert.That(discharges, Is.Not.Empty);
|
||||
Assert.That(discharges.Count(), Is.EqualTo(expectedDischarges.Count()));
|
||||
}
|
||||
// Arrange: Prepare test data
|
||||
var expectedDischarges = new List<Discharge>
|
||||
{
|
||||
new() { Id = ObjectId.GenerateNewId(), DischargeDate = DateTime.UtcNow },
|
||||
new() { Id = ObjectId.GenerateNewId(), DischargeDate = DateTime.UtcNow },
|
||||
new() { Id = ObjectId.GenerateNewId(), DischargeDate = DateTime.UtcNow }
|
||||
};
|
||||
|
||||
await _dischargeRepository.InsertManyAsync(expectedDischarges);
|
||||
|
||||
// Act: Call the method under test
|
||||
var actualDischarges = await _dischargeRepository.FindAll();
|
||||
|
||||
var discharges = actualDischarges.ToList();
|
||||
Assert.That(discharges, Is.Not.Null);
|
||||
Assert.That(discharges, Is.Not.Empty);
|
||||
Assert.That(discharges.Count(), Is.EqualTo(expectedDischarges.Count()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's <c>FindById</c> method returns the matching <c>Discharge</c> document when queried with an existing identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindById_ExistingId_ReturnsDischarge()
|
||||
{
|
||||
var id = ObjectId.GenerateNewId();
|
||||
var expectedDischarge = new Discharge { Id = id, DischargeDate = DateTime.UtcNow };
|
||||
await _dischargeRepository.InsertOneAsync(expectedDischarge);
|
||||
|
||||
var actualDischarge = await _dischargeRepository.FindById(id);
|
||||
|
||||
Assert.That(actualDischarge, Is.Not.Null);
|
||||
Assert.That(actualDischarge?.Id, Is.EqualTo(expectedDischarge.Id));
|
||||
}
|
||||
public async Task FindById_ExistingId_ReturnsDischarge()
|
||||
{
|
||||
var id = ObjectId.GenerateNewId();
|
||||
var expectedDischarge = new Discharge { Id = id, DischargeDate = DateTime.UtcNow };
|
||||
await _dischargeRepository.InsertOneAsync(expectedDischarge);
|
||||
|
||||
var actualDischarge = await _dischargeRepository.FindById(id);
|
||||
|
||||
Assert.That(actualDischarge, Is.Not.Null);
|
||||
Assert.That(actualDischarge?.Id, Is.EqualTo(expectedDischarge.Id));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the discharge repository's FindById method returns <c>null</c> when queried with a non-existent <see cref="ObjectId"/>.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindById_NonExistentId_ReturnsNull()
|
||||
{
|
||||
var id = ObjectId.GenerateNewId();
|
||||
|
||||
var actualDischarge = await _dischargeRepository.FindById(id);
|
||||
|
||||
Assert.That(actualDischarge, Is.Null);
|
||||
}
|
||||
public async Task FindById_NonExistentId_ReturnsNull()
|
||||
{
|
||||
var id = ObjectId.GenerateNewId();
|
||||
|
||||
var actualDischarge = await _dischargeRepository.FindById(id);
|
||||
|
||||
Assert.That(actualDischarge, Is.Null);
|
||||
}
|
||||
|
||||
// [Test]
|
||||
// public async Task FindByUnit_ExistingUnit_ReturnsDischarges()
|
||||
@@ -182,101 +204,120 @@ public class DischargeRepositoryTest
|
||||
// Assert.That(actualDischarges?.ToList().First().PatientLocation?.UnitName, Is.EquivalentTo(expectedDischarges.PatientLocation.UnitName));
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the discharge repository's FindByDestination method returns the matching discharge records when queried with an existing destination.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByDestination_ExistingDestination_ReturnsDischarges()
|
||||
{
|
||||
// Arrange: Prepare test data
|
||||
var destination = "TestDestination";
|
||||
var expectedDischarges =
|
||||
new Discharge
|
||||
{ Id = ObjectId.GenerateNewId(), Destination = destination };
|
||||
await _dischargeRepository.InsertOneAsync(expectedDischarges);
|
||||
|
||||
// Act: Call the method under test
|
||||
var actualDischarges = await _dischargeRepository.FindByDestination(destination);
|
||||
|
||||
// Assert: Verify the result
|
||||
var discharges = actualDischarges?.ToList() ?? [];
|
||||
Assert.That(discharges, Is.Not.Null);
|
||||
Assert.That(discharges.First().Id, Is.EqualTo(expectedDischarges.Id));
|
||||
}
|
||||
public async Task FindByDestination_ExistingDestination_ReturnsDischarges()
|
||||
{
|
||||
// Arrange: Prepare test data
|
||||
var destination = "TestDestination";
|
||||
var expectedDischarges =
|
||||
new Discharge
|
||||
{ Id = ObjectId.GenerateNewId(), Destination = destination };
|
||||
await _dischargeRepository.InsertOneAsync(expectedDischarges);
|
||||
|
||||
// Act: Call the method under test
|
||||
var actualDischarges = await _dischargeRepository.FindByDestination(destination);
|
||||
|
||||
// Assert: Verify the result
|
||||
var discharges = actualDischarges?.ToList() ?? [];
|
||||
Assert.That(discharges, Is.Not.Null);
|
||||
Assert.That(discharges.First().Id, Is.EqualTo(expectedDischarges.Id));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>FindByDestination</c> returns an empty collection when the provided destination does not match any stored discharge records.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByDestination_NonExistentDestination_ReturnsEmptyList()
|
||||
{
|
||||
// Arrange: Use a non-existent destination
|
||||
var destination = "NonExistentDestination";
|
||||
|
||||
// Act: Call the method under test
|
||||
var actualDischarges = await _dischargeRepository.FindByDestination(destination);
|
||||
|
||||
// Assert: Verify that the result is an empty list
|
||||
Assert.That(actualDischarges, Is.Empty);
|
||||
}
|
||||
public async Task FindByDestination_NonExistentDestination_ReturnsEmptyList()
|
||||
{
|
||||
// Arrange: Use a non-existent destination
|
||||
var destination = "NonExistentDestination";
|
||||
|
||||
// Act: Call the method under test
|
||||
var actualDischarges = await _dischargeRepository.FindByDestination(destination);
|
||||
|
||||
// Assert: Verify that the result is an empty list
|
||||
Assert.That(actualDischarges, Is.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="DischargeRepository.FindByPoCId"/> returns the matching discharge
|
||||
/// when a discharge is associated with the supplied point-of-care identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByPoCId_ExistingPoCId_ReturnsDischarges()
|
||||
{
|
||||
// Arrange: Prepare test data
|
||||
var pocId = ObjectId.GenerateNewId();
|
||||
var expectedDischarges =
|
||||
new Discharge
|
||||
{ Id = ObjectId.GenerateNewId(), PointOfCareId = pocId };
|
||||
await _dischargeRepository.InsertOneAsync(expectedDischarges);
|
||||
|
||||
// Act: Call the method under test
|
||||
var actualDischarges = await _dischargeRepository.FindByPoCId(pocId);
|
||||
|
||||
// Assert: Verify the result
|
||||
var discharges = actualDischarges?.ToList() ?? [];
|
||||
Assert.That(discharges, Is.Not.Null);
|
||||
Assert.That(discharges.First().Id, Is.EqualTo(expectedDischarges.Id));
|
||||
}
|
||||
public async Task FindByPoCId_ExistingPoCId_ReturnsDischarges()
|
||||
{
|
||||
// Arrange: Prepare test data
|
||||
var pocId = ObjectId.GenerateNewId();
|
||||
var expectedDischarges =
|
||||
new Discharge
|
||||
{ Id = ObjectId.GenerateNewId(), PointOfCareId = pocId };
|
||||
await _dischargeRepository.InsertOneAsync(expectedDischarges);
|
||||
|
||||
// Act: Call the method under test
|
||||
var actualDischarges = await _dischargeRepository.FindByPoCId(pocId);
|
||||
|
||||
// Assert: Verify the result
|
||||
var discharges = actualDischarges?.ToList() ?? [];
|
||||
Assert.That(discharges, Is.Not.Null);
|
||||
Assert.That(discharges.First().Id, Is.EqualTo(expectedDischarges.Id));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the discharge repository's FindByPoCId method returns an empty list when queried with a non-existent PoCId.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByPoCId_NonExistentPoCId_ReturnsEmptyList()
|
||||
{
|
||||
// Arrange: Use a non-existent PoCId
|
||||
var pocId = ObjectId.GenerateNewId();
|
||||
|
||||
// Act: Call the method under test
|
||||
var actualDischarges = await _dischargeRepository.FindByPoCId(pocId);
|
||||
|
||||
// Assert: Verify that the result is an empty list
|
||||
Assert.That(actualDischarges, Is.Empty);
|
||||
}
|
||||
public async Task FindByPoCId_NonExistentPoCId_ReturnsEmptyList()
|
||||
{
|
||||
// Arrange: Use a non-existent PoCId
|
||||
var pocId = ObjectId.GenerateNewId();
|
||||
|
||||
// Act: Call the method under test
|
||||
var actualDischarges = await _dischargeRepository.FindByPoCId(pocId);
|
||||
|
||||
// Assert: Verify that the result is an empty list
|
||||
Assert.That(actualDischarges, Is.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="DischargeRepository.FindByService"/> returns the matching discharge record when a previously inserted discharge exists for the specified service name.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByService_ExistingService_ReturnsDischarges()
|
||||
{
|
||||
// Arrange: Prepare test data
|
||||
var service = "TestService";
|
||||
var expectedDischarges =
|
||||
new Discharge
|
||||
{ Id = ObjectId.GenerateNewId(), Service = service };
|
||||
await _dischargeRepository.InsertOneAsync(expectedDischarges);
|
||||
|
||||
// Act: Call the method under test
|
||||
var actualDischarges = await _dischargeRepository.FindByService(service);
|
||||
|
||||
// Assert: Verify the result
|
||||
var discharges = actualDischarges?.ToList() ?? [];
|
||||
Assert.That(discharges, Is.Not.Null);
|
||||
Assert.That(discharges.First().Id, Is.EqualTo(expectedDischarges.Id));
|
||||
}
|
||||
public async Task FindByService_ExistingService_ReturnsDischarges()
|
||||
{
|
||||
// Arrange: Prepare test data
|
||||
var service = "TestService";
|
||||
var expectedDischarges =
|
||||
new Discharge
|
||||
{ Id = ObjectId.GenerateNewId(), Service = service };
|
||||
await _dischargeRepository.InsertOneAsync(expectedDischarges);
|
||||
|
||||
// Act: Call the method under test
|
||||
var actualDischarges = await _dischargeRepository.FindByService(service);
|
||||
|
||||
// Assert: Verify the result
|
||||
var discharges = actualDischarges?.ToList() ?? [];
|
||||
Assert.That(discharges, Is.Not.Null);
|
||||
Assert.That(discharges.First().Id, Is.EqualTo(expectedDischarges.Id));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>FindByService</c> returns an empty list when queried with a service name that does not exist in the repository.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByService_NonExistentService_ReturnsEmptyList()
|
||||
{
|
||||
// Arrange: Use a non-existent service
|
||||
var service = "NonExistentService";
|
||||
|
||||
// Act: Call the method under test
|
||||
var actualDischarges = await _dischargeRepository.FindByService(service);
|
||||
|
||||
// Assert: Verify that the result is an empty list
|
||||
Assert.That(actualDischarges, Is.Empty);
|
||||
}
|
||||
public async Task FindByService_NonExistentService_ReturnsEmptyList()
|
||||
{
|
||||
// Arrange: Use a non-existent service
|
||||
var service = "NonExistentService";
|
||||
|
||||
// Act: Call the method under test
|
||||
var actualDischarges = await _dischargeRepository.FindByService(service);
|
||||
|
||||
// Assert: Verify that the result is an empty list
|
||||
Assert.That(actualDischarges, Is.Empty);
|
||||
}
|
||||
|
||||
// [Test]
|
||||
// public async Task GetDischargeByLocation_ExistingLocation_ReturnsDischarge()
|
||||
@@ -296,78 +337,96 @@ public class DischargeRepositoryTest
|
||||
// Assert.That(actualDischarge?.Id, Is.EqualTo(expectedDischarges.Id));
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>GetDischargeByLocation</c> returns <c>null</c> when queried with a location
|
||||
/// that does not exist in the repository.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetDischargeByLocation_NonExistentLocation_ReturnsNull()
|
||||
{
|
||||
// Arrange: Use a non-existent location
|
||||
var location = new PatientLocation("NonExistentUnit", "NonExistentBed", "NonExistentRoom");
|
||||
|
||||
// Act: Call the method under test
|
||||
var actualDischarge = await _dischargeRepository.GetDischargeByLocation(location);
|
||||
|
||||
// Assert: Verify that the result is null
|
||||
Assert.That(actualDischarge, Is.Null);
|
||||
}
|
||||
public async Task GetDischargeByLocation_NonExistentLocation_ReturnsNull()
|
||||
{
|
||||
// Arrange: Use a non-existent location
|
||||
var location = new PatientLocation("NonExistentUnit", "NonExistentBed", "NonExistentRoom");
|
||||
|
||||
// Act: Call the method under test
|
||||
var actualDischarge = await _dischargeRepository.GetDischargeByLocation(location);
|
||||
|
||||
// Assert: Verify that the result is null
|
||||
Assert.That(actualDischarge, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>GetDischargeByPointOfCareId</c> returns the matching <c>Discharge</c> when queried with a point of care ID that already exists in the repository.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetDischargeByPointOfCareId_ExistingId_ReturnsDischarge()
|
||||
{
|
||||
// Arrange: Prepare test data
|
||||
var expectedId = ObjectId.GenerateNewId();
|
||||
var expectedDischarge =
|
||||
new Discharge
|
||||
{ Id = ObjectId.GenerateNewId(), PointOfCareId = expectedId };
|
||||
await _dischargeRepository.InsertOneAsync(expectedDischarge);
|
||||
|
||||
// Act: Call the method under test
|
||||
var actualDischarge = await _dischargeRepository.GetDischargeByPointOfCareId(expectedId);
|
||||
|
||||
// Assert: Verify the result
|
||||
Assert.That(actualDischarge, Is.Not.Null);
|
||||
Assert.That(actualDischarge?.Id, Is.EqualTo(expectedDischarge.Id));
|
||||
}
|
||||
public async Task GetDischargeByPointOfCareId_ExistingId_ReturnsDischarge()
|
||||
{
|
||||
// Arrange: Prepare test data
|
||||
var expectedId = ObjectId.GenerateNewId();
|
||||
var expectedDischarge =
|
||||
new Discharge
|
||||
{ Id = ObjectId.GenerateNewId(), PointOfCareId = expectedId };
|
||||
await _dischargeRepository.InsertOneAsync(expectedDischarge);
|
||||
|
||||
// Act: Call the method under test
|
||||
var actualDischarge = await _dischargeRepository.GetDischargeByPointOfCareId(expectedId);
|
||||
|
||||
// Assert: Verify the result
|
||||
Assert.That(actualDischarge, Is.Not.Null);
|
||||
Assert.That(actualDischarge?.Id, Is.EqualTo(expectedDischarge.Id));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>GetDischargeByPointOfCareId</c> returns <c>null</c> when called with a non-existent point of care ID.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetDischargeByPointOfCareId_NonExistentId_ReturnsNull()
|
||||
{
|
||||
// Arrange: Use a non-existent ID
|
||||
var nonExistentId = ObjectId.GenerateNewId();
|
||||
|
||||
// Act: Call the method under test
|
||||
var actualDischarge = await _dischargeRepository.GetDischargeByPointOfCareId(nonExistentId);
|
||||
|
||||
// Assert: Verify that the result is null
|
||||
Assert.That(actualDischarge, Is.Null);
|
||||
}
|
||||
public async Task GetDischargeByPointOfCareId_NonExistentId_ReturnsNull()
|
||||
{
|
||||
// Arrange: Use a non-existent ID
|
||||
var nonExistentId = ObjectId.GenerateNewId();
|
||||
|
||||
// Act: Call the method under test
|
||||
var actualDischarge = await _dischargeRepository.GetDischargeByPointOfCareId(nonExistentId);
|
||||
|
||||
// Assert: Verify that the result is null
|
||||
Assert.That(actualDischarge, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>GetByPatientId</c> returns the matching <see cref="Discharge"/> record
|
||||
/// when a discharge exists for the specified patient identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetByPatientId_ExistingPatientId_ReturnsDischarge()
|
||||
{
|
||||
// Arrange: Prepare test data
|
||||
var expectedId = ObjectId.GenerateNewId();
|
||||
var expectedDischarge =
|
||||
new Discharge
|
||||
{ Id = ObjectId.GenerateNewId(), PatientId = expectedId };
|
||||
await _dischargeRepository.InsertOneAsync(expectedDischarge);
|
||||
|
||||
// Act: Call the method under test
|
||||
var actualDischarge = await _dischargeRepository.GetByPatientId(expectedId);
|
||||
|
||||
// Assert: Verify the result
|
||||
Assert.That(actualDischarge, Is.Not.Null);
|
||||
Assert.That(actualDischarge?.Id, Is.EqualTo(expectedDischarge.Id));
|
||||
}
|
||||
public async Task GetByPatientId_ExistingPatientId_ReturnsDischarge()
|
||||
{
|
||||
// Arrange: Prepare test data
|
||||
var expectedId = ObjectId.GenerateNewId();
|
||||
var expectedDischarge =
|
||||
new Discharge
|
||||
{ Id = ObjectId.GenerateNewId(), PatientId = expectedId };
|
||||
await _dischargeRepository.InsertOneAsync(expectedDischarge);
|
||||
|
||||
// Act: Call the method under test
|
||||
var actualDischarge = await _dischargeRepository.GetByPatientId(expectedId);
|
||||
|
||||
// Assert: Verify the result
|
||||
Assert.That(actualDischarge, Is.Not.Null);
|
||||
Assert.That(actualDischarge?.Id, Is.EqualTo(expectedDischarge.Id));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the <see cref="DischargeRepository.GetByPatientId"/> repository method returns <c>null</c>
|
||||
/// when called with a patient ID that does not exist in the data store.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetByPatientId_NonExistentPatientId_ReturnsNull()
|
||||
{
|
||||
// Arrange: Use a non-existent patient ID
|
||||
var nonExistentId = ObjectId.GenerateNewId();
|
||||
|
||||
// Act: Call the method under test
|
||||
var actualDischarge = await _dischargeRepository.GetByPatientId(nonExistentId);
|
||||
|
||||
// Assert: Verify that the result is null
|
||||
Assert.That(actualDischarge, Is.Null);
|
||||
}
|
||||
public async Task GetByPatientId_NonExistentPatientId_ReturnsNull()
|
||||
{
|
||||
// Arrange: Use a non-existent patient ID
|
||||
var nonExistentId = ObjectId.GenerateNewId();
|
||||
|
||||
// Act: Call the method under test
|
||||
var actualDischarge = await _dischargeRepository.GetByPatientId(nonExistentId);
|
||||
|
||||
// Assert: Verify that the result is null
|
||||
Assert.That(actualDischarge, Is.Null);
|
||||
}
|
||||
}
|
||||
@@ -13,47 +13,53 @@ namespace adas_core.Test.Repositories;
|
||||
[TestFixture]
|
||||
public class DisplayConfigTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Performs one-time setup for integration tests by initializing the display configuration, card configuration, and detail configuration repositories with test data, including a valid display configuration, a card configuration, and a nurse card details configuration.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task SetUp()
|
||||
{
|
||||
Options.Create(new ApiSettings());
|
||||
_unitRepository = new Mock<IUnitRepository>();
|
||||
_displayCardConfigRepository =
|
||||
new DisplayCardConfigRepository(
|
||||
IntegrationDb.Database,
|
||||
new ApiSettings(),
|
||||
new Mock<ILogger<DisplayCardConfigRepository>>().Object
|
||||
);
|
||||
_displayConfigRepository =
|
||||
new DisplayConfigRepository(
|
||||
IntegrationDb.Database,
|
||||
new ApiSettings(),
|
||||
new Mock<ILogger<DisplayConfigRepository>>().Object,
|
||||
_unitRepository.Object
|
||||
);
|
||||
_displayDetailConfigRepository =
|
||||
new DisplayDetailConfigRepository(
|
||||
IntegrationDb.Database,
|
||||
new ApiSettings(),
|
||||
new Mock<ILogger<DisplayDetailConfigRepository>>().Object
|
||||
);
|
||||
|
||||
await _displayDetailConfigRepository.InsertOneAsync(
|
||||
TestUtilities.CreateValidCardDetailsNurseConfig(_configDisplayCardDetailsId));
|
||||
await _displayCardConfigRepository.InsertOneAsync(TestUtilities.CreateValidCardConfig(_configDisplayCardId));
|
||||
await _displayConfigRepository.InsertOneAsync(TestUtilities.CreateValidDisplayConfig(
|
||||
DisplayConfigEnums.DisplayType.DisplayNurse, _configDisplayId, _configDisplayCardId,
|
||||
_configDisplayCardDetailsId));
|
||||
}
|
||||
public async Task SetUp()
|
||||
{
|
||||
Options.Create(new ApiSettings());
|
||||
_unitRepository = new Mock<IUnitRepository>();
|
||||
_displayCardConfigRepository =
|
||||
new DisplayCardConfigRepository(
|
||||
IntegrationDb.Database,
|
||||
new ApiSettings(),
|
||||
new Mock<ILogger<DisplayCardConfigRepository>>().Object
|
||||
);
|
||||
_displayConfigRepository =
|
||||
new DisplayConfigRepository(
|
||||
IntegrationDb.Database,
|
||||
new ApiSettings(),
|
||||
new Mock<ILogger<DisplayConfigRepository>>().Object,
|
||||
_unitRepository.Object
|
||||
);
|
||||
_displayDetailConfigRepository =
|
||||
new DisplayDetailConfigRepository(
|
||||
IntegrationDb.Database,
|
||||
new ApiSettings(),
|
||||
new Mock<ILogger<DisplayDetailConfigRepository>>().Object
|
||||
);
|
||||
|
||||
await _displayDetailConfigRepository.InsertOneAsync(
|
||||
TestUtilities.CreateValidCardDetailsNurseConfig(_configDisplayCardDetailsId));
|
||||
await _displayCardConfigRepository.InsertOneAsync(TestUtilities.CreateValidCardConfig(_configDisplayCardId));
|
||||
await _displayConfigRepository.InsertOneAsync(TestUtilities.CreateValidDisplayConfig(
|
||||
DisplayConfigEnums.DisplayType.DisplayNurse, _configDisplayId, _configDisplayCardId,
|
||||
_configDisplayCardDetailsId));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// One-time teardown method that cleans up the integration test database by dropping the display configuration collections created during testing.
|
||||
/// </summary>
|
||||
[OneTimeTearDown]
|
||||
public async Task Cleanup()
|
||||
{
|
||||
// Clean up database after tests
|
||||
await IntegrationDb.Database.DropCollectionAsync("config_displays");
|
||||
await IntegrationDb.Database.DropCollectionAsync("config_displays_card");
|
||||
await IntegrationDb.Database.DropCollectionAsync("config_displays_detail");
|
||||
}
|
||||
public async Task Cleanup()
|
||||
{
|
||||
// Clean up database after tests
|
||||
await IntegrationDb.Database.DropCollectionAsync("config_displays");
|
||||
await IntegrationDb.Database.DropCollectionAsync("config_displays_card");
|
||||
await IntegrationDb.Database.DropCollectionAsync("config_displays_detail");
|
||||
}
|
||||
|
||||
private DisplayConfigRepository _displayConfigRepository;
|
||||
private DisplayCardConfigRepository _displayCardConfigRepository;
|
||||
@@ -63,17 +69,20 @@ public class DisplayConfigTest
|
||||
private readonly ObjectId _configDisplayCardId = ObjectId.GenerateNewId();
|
||||
private readonly ObjectId _configDisplayCardDetailsId = ObjectId.GenerateNewId();
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that retrieving a display configuration by its identifier returns a non-null result with the associated card and detail configurations populated.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetByIdShouldReturnAllConfigsAssociated()
|
||||
{
|
||||
var result = await _displayConfigRepository.GetById(_configDisplayId);
|
||||
Assert.That(result, Is.Not.Null);
|
||||
using (Assert.EnterMultipleScope())
|
||||
public async Task GetByIdShouldReturnAllConfigsAssociated()
|
||||
{
|
||||
Assert.That(result.CardConfigId, Is.Not.Null);
|
||||
Assert.That(result.CardConfig, Is.Not.Null);
|
||||
Assert.That(result.DetailConfigId, Is.Not.Null);
|
||||
Assert.That(result.DetailConfig, Is.Not.Null);
|
||||
};
|
||||
}
|
||||
var result = await _displayConfigRepository.GetById(_configDisplayId);
|
||||
Assert.That(result, Is.Not.Null);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(result.CardConfigId, Is.Not.Null);
|
||||
Assert.That(result.CardConfig, Is.Not.Null);
|
||||
Assert.That(result.DetailConfigId, Is.Not.Null);
|
||||
Assert.That(result.DetailConfig, Is.Not.Null);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -6,13 +6,16 @@ public class DisplayRepisitoryTest
|
||||
//private Mock<ILogger<DisplayRepository>> _mockLogger ;
|
||||
//private Mock<IOptions<ApiSettings>> _mockOptionsApiSettings ;
|
||||
|
||||
/// <summary>
|
||||
/// One-time setup method that resets the "displays" collection in the integration database by dropping and recreating it, ensuring a clean state before integration tests run.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task OneTimeSetUp()
|
||||
{
|
||||
//_mockLogger = new Mock<ILogger<DisplayRepository>>();
|
||||
//_mockOptionsApiSettings = new Mock<IOptions<ApiSettings>>();
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("displays");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("displays");
|
||||
}
|
||||
public async Task OneTimeSetUp()
|
||||
{
|
||||
//_mockLogger = new Mock<ILogger<DisplayRepository>>();
|
||||
//_mockOptionsApiSettings = new Mock<IOptions<ApiSettings>>();
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("displays");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("displays");
|
||||
}
|
||||
}
|
||||
@@ -15,25 +15,31 @@ namespace adas_core.Test.Repositories;
|
||||
[Category("Integration")]
|
||||
public class HistoricalConfigChangesRepositoryTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Performs one-time setup for the test fixture by initializing configuration options, a mocked logger, and the <see cref="HistoricalConfigChangesRepository"/> instance used across the tests.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public void Init()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
_logger = new Mock<ILogger<HistoricalConfigChangesRepository>>();
|
||||
|
||||
|
||||
_repository =
|
||||
new HistoricalConfigChangesRepository(_optionsApiSettings, IntegrationDb.Database, _logger.Object);
|
||||
}
|
||||
public void Init()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
_logger = new Mock<ILogger<HistoricalConfigChangesRepository>>();
|
||||
|
||||
|
||||
_repository =
|
||||
new HistoricalConfigChangesRepository(_optionsApiSettings, IntegrationDb.Database, _logger.Object);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the integration test environment by dropping and recreating the <c>historicalConfigChanges</c> collection and then reinitializing the test data. Used as a teardown step to ensure a clean state between tests.
|
||||
/// </summary>
|
||||
[TearDown]
|
||||
public async Task Cleanup()
|
||||
{
|
||||
await IntegrationDb.Database.DropCollectionAsync("historicalConfigChanges");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("historicalConfigChanges");
|
||||
|
||||
await InitializeData();
|
||||
}
|
||||
public async Task Cleanup()
|
||||
{
|
||||
await IntegrationDb.Database.DropCollectionAsync("historicalConfigChanges");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("historicalConfigChanges");
|
||||
|
||||
await InitializeData();
|
||||
}
|
||||
|
||||
private HistoricalConfigChangesRepository _repository;
|
||||
|
||||
@@ -46,167 +52,183 @@ public class HistoricalConfigChangesRepositoryTest
|
||||
|
||||
private Mock<ILogger<HistoricalConfigChangesRepository>> _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Seeds the repository with a series of historical configuration change records for an observation configuration
|
||||
/// (Hemoglobina), illustrating successive code updates from "54321" to "xxxxx" to "11111" to "99999" under the "adas" user.
|
||||
/// </summary>
|
||||
private async Task InitializeData()
|
||||
{
|
||||
var id = ObjectId.GenerateNewId();
|
||||
HistoricalConfigChanges historicalConfigChanges1 = new()
|
||||
{
|
||||
//Id = ObjectId.GenerateNewId(),
|
||||
ConfigType = DisplayConfigEnums.ConfigTypes.ObservationCfg,
|
||||
Time = DateTime.UtcNow,
|
||||
Username = "adas",
|
||||
OldConfig = new ConfigObservation
|
||||
var id = ObjectId.GenerateNewId();
|
||||
HistoricalConfigChanges historicalConfigChanges1 = new()
|
||||
{
|
||||
Id = id,
|
||||
Name = "Hemoglobina",
|
||||
Code = "54321",
|
||||
CodingSystem = "SNM"
|
||||
}.ToJson(),
|
||||
NewConfig = new ConfigObservation
|
||||
//Id = ObjectId.GenerateNewId(),
|
||||
ConfigType = DisplayConfigEnums.ConfigTypes.ObservationCfg,
|
||||
Time = DateTime.UtcNow,
|
||||
Username = "adas",
|
||||
OldConfig = new ConfigObservation
|
||||
{
|
||||
Id = id,
|
||||
Name = "Hemoglobina",
|
||||
Code = "54321",
|
||||
CodingSystem = "SNM"
|
||||
}.ToJson(),
|
||||
NewConfig = new ConfigObservation
|
||||
{
|
||||
Id = id,
|
||||
Name = "Hemoglobina",
|
||||
Code = "xxxxx",
|
||||
CodingSystem = "SNM"
|
||||
}.ToJson()
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(historicalConfigChanges1);
|
||||
|
||||
HistoricalConfigChanges historicalConfigChanges2 = new()
|
||||
{
|
||||
Id = id,
|
||||
Name = "Hemoglobina",
|
||||
Code = "xxxxx",
|
||||
CodingSystem = "SNM"
|
||||
}.ToJson()
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(historicalConfigChanges1);
|
||||
|
||||
HistoricalConfigChanges historicalConfigChanges2 = new()
|
||||
{
|
||||
//Id = ObjectId.GenerateNewId(),
|
||||
ConfigType = DisplayConfigEnums.ConfigTypes.ObservationCfg,
|
||||
Time = DateTime.UtcNow,
|
||||
Username = "adas",
|
||||
OldConfig = new ConfigObservation
|
||||
//Id = ObjectId.GenerateNewId(),
|
||||
ConfigType = DisplayConfigEnums.ConfigTypes.ObservationCfg,
|
||||
Time = DateTime.UtcNow,
|
||||
Username = "adas",
|
||||
OldConfig = new ConfigObservation
|
||||
{
|
||||
Id = id,
|
||||
Name = "Hemoglobina",
|
||||
Code = "xxxxx",
|
||||
CodingSystem = "SNM"
|
||||
}.ToJson(),
|
||||
NewConfig = new ConfigObservation
|
||||
{
|
||||
Id = id,
|
||||
Name = "Hemoglobina",
|
||||
Code = "11111",
|
||||
CodingSystem = "SNM"
|
||||
}.ToJson()
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(historicalConfigChanges2);
|
||||
|
||||
HistoricalConfigChanges historicalConfigChanges3 = new()
|
||||
{
|
||||
Id = id,
|
||||
Name = "Hemoglobina",
|
||||
Code = "xxxxx",
|
||||
CodingSystem = "SNM"
|
||||
}.ToJson(),
|
||||
NewConfig = new ConfigObservation
|
||||
{
|
||||
Id = id,
|
||||
Name = "Hemoglobina",
|
||||
Code = "11111",
|
||||
CodingSystem = "SNM"
|
||||
}.ToJson()
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(historicalConfigChanges2);
|
||||
|
||||
HistoricalConfigChanges historicalConfigChanges3 = new()
|
||||
{
|
||||
//Id = ObjectId.GenerateNewId(),
|
||||
ConfigType = DisplayConfigEnums.ConfigTypes.ObservationCfg,
|
||||
Time = DateTime.UtcNow,
|
||||
Username = "adas",
|
||||
OldConfig = new ConfigObservation
|
||||
{
|
||||
Id = id,
|
||||
Name = "Hemoglobina",
|
||||
Code = "111111",
|
||||
CodingSystem = "SNM"
|
||||
}.ToJson(),
|
||||
NewConfig = new ConfigObservation
|
||||
{
|
||||
Id = id,
|
||||
Name = "Hemoglobina",
|
||||
Code = "99999",
|
||||
CodingSystem = "SNM"
|
||||
}.ToJson()
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(historicalConfigChanges3);
|
||||
}
|
||||
//Id = ObjectId.GenerateNewId(),
|
||||
ConfigType = DisplayConfigEnums.ConfigTypes.ObservationCfg,
|
||||
Time = DateTime.UtcNow,
|
||||
Username = "adas",
|
||||
OldConfig = new ConfigObservation
|
||||
{
|
||||
Id = id,
|
||||
Name = "Hemoglobina",
|
||||
Code = "111111",
|
||||
CodingSystem = "SNM"
|
||||
}.ToJson(),
|
||||
NewConfig = new ConfigObservation
|
||||
{
|
||||
Id = id,
|
||||
Name = "Hemoglobina",
|
||||
Code = "99999",
|
||||
CodingSystem = "SNM"
|
||||
}.ToJson()
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(historicalConfigChanges3);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's <c>FindAll</c> method returns a non-null collection containing exactly three historical configuration change records after a cleanup operation.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Get_HistoricalConfigChanges_returns_count_3()
|
||||
{
|
||||
await Cleanup();
|
||||
|
||||
var result = await _repository.FindAll();
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Has.Count.EqualTo(3));
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public async Task HistoricalConfigChanges_returns_diferent_document()
|
||||
{
|
||||
await Cleanup();
|
||||
var id = ObjectId.GenerateNewId();
|
||||
var resultList = await _repository.FindAll();
|
||||
var result = resultList.FirstOrDefault();
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
|
||||
Debug.Assert(result != null, nameof(result) + " != null");
|
||||
HistoricalConfigChanges updatedHistoricalConfigChanges = new()
|
||||
public async Task Get_HistoricalConfigChanges_returns_count_3()
|
||||
{
|
||||
Id = result.Id,
|
||||
ConfigType = DisplayConfigEnums.ConfigTypes.ObservationCfg,
|
||||
Time = DateTime.UtcNow,
|
||||
Username = "admin",
|
||||
OldConfig = new ConfigObservation
|
||||
{
|
||||
Id = id,
|
||||
Name = "Hemoglobina",
|
||||
Code = "12345",
|
||||
CodingSystem = "SNM"
|
||||
}.ToJson(),
|
||||
NewConfig = new ConfigObservation
|
||||
{
|
||||
Id = id,
|
||||
Name = "Hemoglobina",
|
||||
Code = "54321",
|
||||
CodingSystem = "SNM"
|
||||
}.ToJson()
|
||||
};
|
||||
await Cleanup();
|
||||
|
||||
var result = await _repository.FindAll();
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Has.Count.EqualTo(3));
|
||||
}
|
||||
|
||||
|
||||
var updated = await _repository.Update(updatedHistoricalConfigChanges);
|
||||
using (Assert.EnterMultipleScope())
|
||||
/// <summary>
|
||||
/// Verifies that the repository <c>Update</c> operation for a <see cref="HistoricalConfigChanges"/> document returns a non-null result whose properties correspond to the updated record, after cleaning up existing data and retrieving an existing entry to be modified.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task HistoricalConfigChanges_returns_diferent_document()
|
||||
{
|
||||
Assert.That(updated, Is.Not.Null);
|
||||
Assert.That(result.Time, Is.EqualTo(updated?.Time));
|
||||
Assert.That(result.Id, Is.EqualTo(updated?.Id));
|
||||
Assert.That(result.Username, Is.EqualTo(updated?.Username));
|
||||
Assert.That(result.ConfigType, Is.EqualTo(updated?.ConfigType));
|
||||
Assert.That(result.OldConfig, Is.EqualTo(updated?.OldConfig));
|
||||
Assert.That(result.NewConfig, Is.EqualTo(updated?.NewConfig));
|
||||
};
|
||||
}
|
||||
await Cleanup();
|
||||
var id = ObjectId.GenerateNewId();
|
||||
var resultList = await _repository.FindAll();
|
||||
var result = resultList.FirstOrDefault();
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
|
||||
Debug.Assert(result != null, nameof(result) + " != null");
|
||||
HistoricalConfigChanges updatedHistoricalConfigChanges = new()
|
||||
{
|
||||
Id = result.Id,
|
||||
ConfigType = DisplayConfigEnums.ConfigTypes.ObservationCfg,
|
||||
Time = DateTime.UtcNow,
|
||||
Username = "admin",
|
||||
OldConfig = new ConfigObservation
|
||||
{
|
||||
Id = id,
|
||||
Name = "Hemoglobina",
|
||||
Code = "12345",
|
||||
CodingSystem = "SNM"
|
||||
}.ToJson(),
|
||||
NewConfig = new ConfigObservation
|
||||
{
|
||||
Id = id,
|
||||
Name = "Hemoglobina",
|
||||
Code = "54321",
|
||||
CodingSystem = "SNM"
|
||||
}.ToJson()
|
||||
};
|
||||
|
||||
|
||||
var updated = await _repository.Update(updatedHistoricalConfigChanges);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(updated, Is.Not.Null);
|
||||
Assert.That(result.Time, Is.EqualTo(updated?.Time));
|
||||
Assert.That(result.Id, Is.EqualTo(updated?.Id));
|
||||
Assert.That(result.Username, Is.EqualTo(updated?.Username));
|
||||
Assert.That(result.ConfigType, Is.EqualTo(updated?.ConfigType));
|
||||
Assert.That(result.OldConfig, Is.EqualTo(updated?.OldConfig));
|
||||
Assert.That(result.NewConfig, Is.EqualTo(updated?.NewConfig));
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="_repository"/>.FindLastHistoricalConfigChangesByUser returns exactly three historical configuration changes for the user "adas" after cleanup.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindLastHistoricalConfigChangesByUser_returns_3()
|
||||
{
|
||||
await Cleanup();
|
||||
var result = await _repository.FindLastHistoricalConfigChangesByUser("adas");
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Has.Count.EqualTo(3));
|
||||
}
|
||||
public async Task FindLastHistoricalConfigChangesByUser_returns_3()
|
||||
{
|
||||
await Cleanup();
|
||||
var result = await _repository.FindLastHistoricalConfigChangesByUser("adas");
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Has.Count.EqualTo(3));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that deleting a historical config change entry reduces the total count of records from three to two in the repository.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Delete_HistoricalConfigChanges_returns_count_2()
|
||||
{
|
||||
await Cleanup();
|
||||
var resultList = await _repository.FindAll();
|
||||
Assert.That(resultList, Has.Count.EqualTo(3));
|
||||
|
||||
var result = resultList.FirstOrDefault();
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Debug.Assert(result != null, nameof(result) + " != null");
|
||||
var deleted = await _repository.DeleteAsync(result.Id);
|
||||
|
||||
Assert.That(deleted, Is.Not.Null);
|
||||
|
||||
var resultAfterDelete = await _repository.FindAll();
|
||||
Assert.That(resultAfterDelete, Has.Count.EqualTo(2));
|
||||
}
|
||||
public async Task Delete_HistoricalConfigChanges_returns_count_2()
|
||||
{
|
||||
await Cleanup();
|
||||
var resultList = await _repository.FindAll();
|
||||
Assert.That(resultList, Has.Count.EqualTo(3));
|
||||
|
||||
var result = resultList.FirstOrDefault();
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Debug.Assert(result != null, nameof(result) + " != null");
|
||||
var deleted = await _repository.DeleteAsync(result.Id);
|
||||
|
||||
Assert.That(deleted, Is.Not.Null);
|
||||
|
||||
var resultAfterDelete = await _repository.FindAll();
|
||||
Assert.That(resultAfterDelete, Has.Count.EqualTo(2));
|
||||
}
|
||||
}
|
||||
@@ -17,48 +17,60 @@ public class IntegrationDb
|
||||
public static IMongoDatabase Database { get; private set; } = null!;
|
||||
public static string DatabaseName { get; } = "IntegrationTestDb";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the MongoDB integration test environment by starting a MongoDB runner, configuring MongoDB conventions and BSON class mappings, establishing a client from the runner's connection string, and obtaining the target database used by integration tests.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public void InitIntegrationTests()
|
||||
{
|
||||
StartMongoDbRunner().Wait();
|
||||
MongoDbHostBuilderExtension.ConfigureMongoDbConventions();
|
||||
MongoDbHostBuilderExtension.ConfigureRegisterMapClass();
|
||||
Client = new MongoClient(Runner?.ConnectionString);
|
||||
Database = Client.GetDatabase(DatabaseName);
|
||||
}
|
||||
public void InitIntegrationTests()
|
||||
{
|
||||
StartMongoDbRunner().Wait();
|
||||
MongoDbHostBuilderExtension.ConfigureMongoDbConventions();
|
||||
MongoDbHostBuilderExtension.ConfigureRegisterMapClass();
|
||||
Client = new MongoClient(Runner?.ConnectionString);
|
||||
Database = Client.GetDatabase(DatabaseName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts the MongoDB test runner and waits for the server to become available by issuing a ping command, retrying on failure until the configured timeout is reached.
|
||||
/// If the server does not become available within the timeout, the runner is disposed and a <see cref="TimeoutException"/> is thrown.
|
||||
/// </summary>
|
||||
/// <exception cref="TimeoutException">Thrown when the MongoDB server does not respond within the configured timeout period.</exception>
|
||||
private static async Task StartMongoDbRunner()
|
||||
{
|
||||
Runner = MongoDbRunner.Start();
|
||||
|
||||
// Wait for the MongoDB server to become available or timeout.
|
||||
var startTime = DateTime.UtcNow;
|
||||
while (DateTime.UtcNow - startTime < TimeSpan.FromSeconds(TimeoutInSeconds))
|
||||
try
|
||||
{
|
||||
var testClient = new MongoClient(Runner.ConnectionString);
|
||||
var adminDb = testClient.GetDatabase("admin");
|
||||
await adminDb.RunCommandAsync((Command<BsonDocument>)"{ping:1}");
|
||||
return; // MongoDB server is available, continue.
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Retry after a short delay.
|
||||
await Task.Delay(500);
|
||||
}
|
||||
|
||||
// Timeout reached, dispose the runner and throw an exception.
|
||||
Runner.Dispose();
|
||||
throw new TimeoutException("Timeout while starting MongoDB server.");
|
||||
}
|
||||
{
|
||||
Runner = MongoDbRunner.Start();
|
||||
|
||||
// Wait for the MongoDB server to become available or timeout.
|
||||
var startTime = DateTime.UtcNow;
|
||||
while (DateTime.UtcNow - startTime < TimeSpan.FromSeconds(TimeoutInSeconds))
|
||||
try
|
||||
{
|
||||
var testClient = new MongoClient(Runner.ConnectionString);
|
||||
var adminDb = testClient.GetDatabase("admin");
|
||||
await adminDb.RunCommandAsync((Command<BsonDocument>)"{ping:1}");
|
||||
return; // MongoDB server is available, continue.
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Retry after a short delay.
|
||||
await Task.Delay(500);
|
||||
}
|
||||
|
||||
// Timeout reached, dispose the runner and throw an exception.
|
||||
Runner.Dispose();
|
||||
throw new TimeoutException("Timeout while starting MongoDB server.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs one-time teardown for integration tests by disposing the <see cref="Client"/> and <see cref="Runner"/> resources.
|
||||
/// Safely handles cases where either resource has not been initialized by using null-conditional disposal.
|
||||
/// </summary>
|
||||
[OneTimeTearDown]
|
||||
public void TeardownIntegrationTests()
|
||||
{
|
||||
Client?.Dispose();
|
||||
Runner?.Dispose();
|
||||
//_runner = null;
|
||||
//_client = null;
|
||||
//_fakeDb = null;
|
||||
}
|
||||
public void TeardownIntegrationTests()
|
||||
{
|
||||
Client?.Dispose();
|
||||
Runner?.Dispose();
|
||||
//_runner = null;
|
||||
//_client = null;
|
||||
//_fakeDb = null;
|
||||
}
|
||||
}
|
||||
@@ -10,129 +10,149 @@ namespace adas_core.Test.Repositories;
|
||||
[TestFixture]
|
||||
public class MasterListRepositoryTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Performs one-time initialization for the test fixture by configuring <see cref="ApiSettings"/> with the expected master list property names, resetting the "MasterLists" collection in the integration database, and creating a <see cref="MasterListRepository{MasterList}"/> instance for use across tests.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
// Set up MongoDB connection
|
||||
// var client = new MongoClient("mongodb://localhost:27017");
|
||||
// _database = client.GetDatabase("TestDatabase");
|
||||
|
||||
// Initialize ApiSettings
|
||||
_apiSettings = new ApiSettings
|
||||
public async Task Init()
|
||||
{
|
||||
AltableOptionList = "altableOptionList",
|
||||
AllergyList = "allergyList",
|
||||
DestinationList = "destinationList",
|
||||
DiagnosisList = "diagnosisList",
|
||||
DischargeStatusList = "dischargeStatusList",
|
||||
DoctorList = "doctorList",
|
||||
DoctorTypeList = "doctorTypeList",
|
||||
InternalDestinationList = "internalDestinationList",
|
||||
InsulationList = "insulationList",
|
||||
LanguageBarrierList = "languageBarrierList",
|
||||
MobilityOptionList = "mobilityOptionList",
|
||||
OriginList = "originList",
|
||||
PatientStatusList = "patientStatusList",
|
||||
ProcedureList = "procedureList",
|
||||
TestList = "testList",
|
||||
ServiceList = "serviceList",
|
||||
TherapeuticCeilingList = "therapeuticCeilingList",
|
||||
TreatmentList = "treatmentList",
|
||||
VisitOptionList = "visitOptionList",
|
||||
AccessControlList = "accessControlList"
|
||||
};
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
|
||||
// Insert sample data
|
||||
await IntegrationDb.Database.DropCollectionAsync("MasterLists");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("MasterLists");
|
||||
|
||||
// Create the repository instance
|
||||
_repository = new MasterListRepository<MasterList>(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
// var masterListCollection = _database.GetCollection<MasterList>("MasterLists");
|
||||
// var sampleData = new List<MasterList>
|
||||
// {
|
||||
// new MasterList { Id = ObjectId.GenerateNewId(), Name = "Sample MasterList 1" },
|
||||
// new MasterList { Id = ObjectId.GenerateNewId(), Name = "Sample MasterList 2" }
|
||||
// };
|
||||
// await masterListCollection.InsertManyAsync(sampleData);
|
||||
}
|
||||
// Set up MongoDB connection
|
||||
// var client = new MongoClient("mongodb://localhost:27017");
|
||||
// _database = client.GetDatabase("TestDatabase");
|
||||
|
||||
// Initialize ApiSettings
|
||||
_apiSettings = new ApiSettings
|
||||
{
|
||||
AltableOptionList = "altableOptionList",
|
||||
AllergyList = "allergyList",
|
||||
DestinationList = "destinationList",
|
||||
DiagnosisList = "diagnosisList",
|
||||
DischargeStatusList = "dischargeStatusList",
|
||||
DoctorList = "doctorList",
|
||||
DoctorTypeList = "doctorTypeList",
|
||||
InternalDestinationList = "internalDestinationList",
|
||||
InsulationList = "insulationList",
|
||||
LanguageBarrierList = "languageBarrierList",
|
||||
MobilityOptionList = "mobilityOptionList",
|
||||
OriginList = "originList",
|
||||
PatientStatusList = "patientStatusList",
|
||||
ProcedureList = "procedureList",
|
||||
TestList = "testList",
|
||||
ServiceList = "serviceList",
|
||||
TherapeuticCeilingList = "therapeuticCeilingList",
|
||||
TreatmentList = "treatmentList",
|
||||
VisitOptionList = "visitOptionList",
|
||||
AccessControlList = "accessControlList"
|
||||
};
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
|
||||
// Insert sample data
|
||||
await IntegrationDb.Database.DropCollectionAsync("MasterLists");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("MasterLists");
|
||||
|
||||
// Create the repository instance
|
||||
_repository = new MasterListRepository<MasterList>(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
// var masterListCollection = _database.GetCollection<MasterList>("MasterLists");
|
||||
// var sampleData = new List<MasterList>
|
||||
// {
|
||||
// new MasterList { Id = ObjectId.GenerateNewId(), Name = "Sample MasterList 1" },
|
||||
// new MasterList { Id = ObjectId.GenerateNewId(), Name = "Sample MasterList 2" }
|
||||
// };
|
||||
// await masterListCollection.InsertManyAsync(sampleData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs one-time cleanup after integration test execution by dropping the <c>MasterLists</c> collection from the integration test database to ensure a clean state between test runs.
|
||||
/// </summary>
|
||||
[OneTimeTearDown]
|
||||
public async Task Cleanup()
|
||||
{
|
||||
// Clean up database after tests
|
||||
await IntegrationDb.Database.DropCollectionAsync("MasterLists");
|
||||
}
|
||||
public async Task Cleanup()
|
||||
{
|
||||
// Clean up database after tests
|
||||
await IntegrationDb.Database.DropCollectionAsync("MasterLists");
|
||||
}
|
||||
|
||||
private MasterListRepository<MasterList> _repository;
|
||||
private ApiSettings _apiSettings;
|
||||
private IOptions<ApiSettings> _optionsApiSettings;
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="MasterList"/> entities are correctly persisted in the repository via <c>InsertOneAsync</c>,
|
||||
/// by inserting an entity and confirming it can be retrieved by its identifier using the default locale.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task InsertOneAsync_ShouldInsertEntity()
|
||||
{
|
||||
// Arrange
|
||||
var masterList = new MasterList { Id = ObjectId.GenerateNewId(), Name = "Test MasterList" };
|
||||
|
||||
// Act
|
||||
await _repository.InsertOneAsync(masterList);
|
||||
await _repository.GetAll();
|
||||
var result = await _repository.FindById(masterList.Id, LocaleEnum.Default);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result?.Name, Is.EqualTo("Test MasterList"));
|
||||
}
|
||||
public async Task InsertOneAsync_ShouldInsertEntity()
|
||||
{
|
||||
// Arrange
|
||||
var masterList = new MasterList { Id = ObjectId.GenerateNewId(), Name = "Test MasterList" };
|
||||
|
||||
// Act
|
||||
await _repository.InsertOneAsync(masterList);
|
||||
await _repository.GetAll();
|
||||
var result = await _repository.FindById(masterList.Id, LocaleEnum.Default);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result?.Name, Is.EqualTo("Test MasterList"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's Delete operation successfully removes a MasterList entity, ensuring that a subsequent lookup by id returns no result.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Delete_ShouldDeleteEntity()
|
||||
{
|
||||
// Arrange
|
||||
var masterList = new MasterList { Id = ObjectId.GenerateNewId(), Name = "ToDelete MasterList" };
|
||||
await _repository.InsertOneAsync(masterList);
|
||||
|
||||
// Act
|
||||
await _repository.Delete(masterList.Id);
|
||||
var result = await _repository.FindById(masterList.Id, LocaleEnum.Default);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
public async Task Delete_ShouldDeleteEntity()
|
||||
{
|
||||
// Arrange
|
||||
var masterList = new MasterList { Id = ObjectId.GenerateNewId(), Name = "ToDelete MasterList" };
|
||||
await _repository.InsertOneAsync(masterList);
|
||||
|
||||
// Act
|
||||
await _repository.Delete(masterList.Id);
|
||||
var result = await _repository.FindById(masterList.Id, LocaleEnum.Default);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's <c>Update</c> method successfully persists changes to an existing <see cref="MasterList"/> entity, allowing the modified record to be retrieved by its identifier with the updated values.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Update_ShouldUpdateEntity()
|
||||
{
|
||||
// Arrange
|
||||
var masterList = new MasterList { Id = ObjectId.GenerateNewId(), Name = "Original MasterList" };
|
||||
await _repository.InsertOneAsync(masterList);
|
||||
masterList.Name = "Updated MasterList";
|
||||
|
||||
// Act
|
||||
await _repository.Update(masterList);
|
||||
var result = await _repository.FindById(masterList.Id, LocaleEnum.Default);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result?.Name, Is.EqualTo("Updated MasterList"));
|
||||
}
|
||||
public async Task Update_ShouldUpdateEntity()
|
||||
{
|
||||
// Arrange
|
||||
var masterList = new MasterList { Id = ObjectId.GenerateNewId(), Name = "Original MasterList" };
|
||||
await _repository.InsertOneAsync(masterList);
|
||||
masterList.Name = "Updated MasterList";
|
||||
|
||||
// Act
|
||||
await _repository.Update(masterList);
|
||||
var result = await _repository.FindById(masterList.Id, LocaleEnum.Default);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result?.Name, Is.EqualTo("Updated MasterList"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's FindById method returns the matching entity when a master list with the specified identifier exists in the data store.
|
||||
/// </summary>
|
||||
/// <returns>A task representing the asynchronous test execution.</returns>
|
||||
[Test]
|
||||
public async Task FindById_ShouldReturnEntity_WhenFound()
|
||||
{
|
||||
// Arrange
|
||||
var masterList = new MasterList { Id = ObjectId.GenerateNewId(), Name = "FindById MasterList" };
|
||||
await _repository.InsertOneAsync(masterList);
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindById(masterList.Id, LocaleEnum.Default);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result?.Name, Is.EqualTo("FindById MasterList"));
|
||||
}
|
||||
public async Task FindById_ShouldReturnEntity_WhenFound()
|
||||
{
|
||||
// Arrange
|
||||
var masterList = new MasterList { Id = ObjectId.GenerateNewId(), Name = "FindById MasterList" };
|
||||
await _repository.InsertOneAsync(masterList);
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindById(masterList.Id, LocaleEnum.Default);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result?.Name, Is.EqualTo("FindById MasterList"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task FindById_WithDifferentLocale_ShouldReturnEntity_WhenFound()
|
||||
@@ -233,30 +253,36 @@ public class MasterListRepositoryTest
|
||||
Assert.That(resultEs?.Options[0].Name, Is.EqualTo("Opción 1"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's FindByName method returns the matching entity when an entity with the specified name exists in the data store.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByName_ShouldReturnEntity_WhenFound()
|
||||
{
|
||||
// Arrange
|
||||
var masterList = new MasterList { Id = ObjectId.GenerateNewId(), Name = "FindByName MasterList" };
|
||||
await _repository.InsertOneAsync(masterList);
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindByName(masterList.Name);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result?.Name, Is.EqualTo("FindByName MasterList"));
|
||||
}
|
||||
public async Task FindByName_ShouldReturnEntity_WhenFound()
|
||||
{
|
||||
// Arrange
|
||||
var masterList = new MasterList { Id = ObjectId.GenerateNewId(), Name = "FindByName MasterList" };
|
||||
await _repository.InsertOneAsync(masterList);
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindByName(masterList.Name);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result?.Name, Is.EqualTo("FindByName MasterList"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's GetAll method returns all entities, ensuring the result contains at least two items.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetAll_ShouldReturnAllEntities()
|
||||
{
|
||||
// Act
|
||||
var result = await _repository.GetAll();
|
||||
|
||||
// Assert
|
||||
Assert.That(result.Count(), Is.GreaterThanOrEqualTo(2));
|
||||
}
|
||||
public async Task GetAll_ShouldReturnAllEntities()
|
||||
{
|
||||
// Act
|
||||
var result = await _repository.GetAll();
|
||||
|
||||
// Assert
|
||||
Assert.That(result.Count(), Is.GreaterThanOrEqualTo(2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetMasterListByIdAndSearchOptiionsByLocale()
|
||||
|
||||
@@ -12,31 +12,34 @@ namespace adas_core.Test.Repositories;
|
||||
[Category("Integration")]
|
||||
public class MedicineRepositoryTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Performs one-time initialization for integration tests by seeding the medicines collection with a test record and verifying it can be retrieved by code or note.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
_testMedicine = new Medicine
|
||||
public async Task Init()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Codes = ["12345"],
|
||||
Notes = ["note1"],
|
||||
Name = "test",
|
||||
Group = [MedicineEnum.Group.Metabolic.ToString()]
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("medicines");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("medicines");
|
||||
|
||||
_repository = new MedicineRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(_testMedicine);
|
||||
|
||||
var result = _repository.GetMedicineByCodeOrNote(["12345"]);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
_testMedicine = new Medicine
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Codes = ["12345"],
|
||||
Notes = ["note1"],
|
||||
Name = "test",
|
||||
Group = [MedicineEnum.Group.Metabolic.ToString()]
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("medicines");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("medicines");
|
||||
|
||||
_repository = new MedicineRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(_testMedicine);
|
||||
|
||||
var result = _repository.GetMedicineByCodeOrNote(["12345"]);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
|
||||
private MedicineRepository _repository = null!;
|
||||
|
||||
@@ -49,14 +52,17 @@ public class MedicineRepositoryTest
|
||||
|
||||
private IOptions<ApiSettings> _optionsApiSettings = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>GetMedicineByCodeOrNote</c> returns a non-null, empty list when invoked with an array containing an empty string.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Get_Medicines_Of_Treatments_Return_Empty_List()
|
||||
{
|
||||
var result = await _repository.GetMedicineByCodeOrNote([""]);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
public async Task Get_Medicines_Of_Treatments_Return_Empty_List()
|
||||
{
|
||||
var result = await _repository.GetMedicineByCodeOrNote([""]);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Get_Medicines_Of_Treatments_By_Code_When_Have_Code_And_Notes_Return_Paracetamol()
|
||||
@@ -83,50 +89,63 @@ public class MedicineRepositoryTest
|
||||
Assert.That(result, Has.Count.EqualTo(1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that the repository returns a non-null medicine when a valid medicine code is found.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetMedicine_Find_Code_Return_Medicine()
|
||||
{
|
||||
var result = await _repository.GetMedicine("12345");
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetMedicine_Not_Find_Code_Return_Empty()
|
||||
{
|
||||
var result = await _repository.GetMedicine("123456");
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetMedicine_Find_Note_Return_Medicine()
|
||||
{
|
||||
var result = await _repository.GetMedicine("note1");
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task UpdateMedicine_Return_Medicine()
|
||||
{
|
||||
var updateMedicine = new Medicine
|
||||
public async Task GetMedicine_Find_Code_Return_Medicine()
|
||||
{
|
||||
Id = _testMedicine.Id,
|
||||
Codes = ["12345"],
|
||||
Notes = ["note1", "note2", "note3"],
|
||||
Name = "test",
|
||||
Group = [MedicineEnum.Group.Metabolic.ToString()]
|
||||
};
|
||||
|
||||
var result = await _repository.UpdateMedicine(updateMedicine);
|
||||
var resultUpdate = await _repository.GetMedicineById(_testMedicine.Id);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
|
||||
var result = await _repository.GetMedicine("12345");
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(resultUpdate, Is.Not.Null);
|
||||
Assert.That(resultUpdate?.Notes != null && resultUpdate.Notes.Contains("note3"), Is.True);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's <c>GetMedicine</c> method returns <c>null</c> when the provided medicine code does not match any existing record.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetMedicine_Not_Find_Code_Return_Empty()
|
||||
{
|
||||
var result = await _repository.GetMedicine("123456");
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository returns a non-null medicine when a medicine is found
|
||||
/// by the supplied note identifier ("note1"), confirming successful lookup by note.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetMedicine_Find_Note_Return_Medicine()
|
||||
{
|
||||
var result = await _repository.GetMedicine("note1");
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that UpdateMedicine returns the updated medicine and that the changes are persisted and retrievable via GetMedicineById, including the updated notes collection.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task UpdateMedicine_Return_Medicine()
|
||||
{
|
||||
var updateMedicine = new Medicine
|
||||
{
|
||||
Id = _testMedicine.Id,
|
||||
Codes = ["12345"],
|
||||
Notes = ["note1", "note2", "note3"],
|
||||
Name = "test",
|
||||
Group = [MedicineEnum.Group.Metabolic.ToString()]
|
||||
};
|
||||
|
||||
var result = await _repository.UpdateMedicine(updateMedicine);
|
||||
var resultUpdate = await _repository.GetMedicineById(_testMedicine.Id);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(resultUpdate, Is.Not.Null);
|
||||
Assert.That(resultUpdate?.Notes != null && resultUpdate.Notes.Contains("note3"), Is.True);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -27,97 +27,109 @@ public class MongodbMigrationTest
|
||||
private static readonly DateTime Now = DateTime.Now;
|
||||
private static readonly ObjectId PatientId = ObjectId.GenerateNewId();
|
||||
|
||||
/// <summary>
|
||||
/// Performs one-time initialization for the test fixture by dropping and recreating the "patients" collection, instantiating the PatientRepository, and seeding it with three test Patient records (one of which has a discharge time set to the current time) to verify they are persisted.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("patients");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("patients");
|
||||
|
||||
_repository = new PatientRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
var patients = new List<Patient>
|
||||
public async Task Init()
|
||||
{
|
||||
new ()
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("patients");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("patients");
|
||||
|
||||
_repository = new PatientRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
var patients = new List<Patient>
|
||||
{
|
||||
Id = PatientId,
|
||||
PatientId = "patientId1",
|
||||
PointOfCareId = ObjectId.GenerateNewId(),
|
||||
Bed = "bed1",
|
||||
PatientNumber = "patientNumber1",
|
||||
Person = new Person
|
||||
new ()
|
||||
{
|
||||
FirstName = "firstName1",
|
||||
LastName = "lastName1",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
Id = PatientId,
|
||||
PatientId = "patientId1",
|
||||
PointOfCareId = ObjectId.GenerateNewId(),
|
||||
Bed = "bed1",
|
||||
PatientNumber = "patientNumber1",
|
||||
Person = new Person
|
||||
{
|
||||
FirstName = "firstName1",
|
||||
LastName = "lastName1",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
},
|
||||
DisTime = Now
|
||||
},
|
||||
DisTime = Now
|
||||
},
|
||||
new ()
|
||||
{
|
||||
PatientId = "patientId2",
|
||||
PointOfCareId = ObjectId.GenerateNewId(),
|
||||
Bed = "bed2",
|
||||
PatientNumber = "patientNumber2",
|
||||
Person = new Person
|
||||
new ()
|
||||
{
|
||||
FirstName = "firstName2",
|
||||
LastName = "lastName2",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
},
|
||||
new ()
|
||||
{
|
||||
PatientId = "patientId3",
|
||||
PointOfCareId = ObjectId.GenerateNewId(),
|
||||
Bed = "bed3",
|
||||
PatientNumber = "patientNumber3",
|
||||
Person = new Person
|
||||
PatientId = "patientId2",
|
||||
PointOfCareId = ObjectId.GenerateNewId(),
|
||||
Bed = "bed2",
|
||||
PatientNumber = "patientNumber2",
|
||||
Person = new Person
|
||||
{
|
||||
FirstName = "firstName2",
|
||||
LastName = "lastName2",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
},
|
||||
new ()
|
||||
{
|
||||
FirstName = "firstName3",
|
||||
LastName = "lastName3",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
PatientId = "patientId3",
|
||||
PointOfCareId = ObjectId.GenerateNewId(),
|
||||
Bed = "bed3",
|
||||
PatientNumber = "patientNumber3",
|
||||
Person = new Person
|
||||
{
|
||||
FirstName = "firstName3",
|
||||
LastName = "lastName3",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
await _repository.InsertManyAsync(patients);
|
||||
Assert.That(await _repository.Collection.CountDocumentsAsync(_ => true), Is.EqualTo(3));
|
||||
}
|
||||
};
|
||||
|
||||
await _repository.InsertManyAsync(patients);
|
||||
Assert.That(await _repository.Collection.CountDocumentsAsync(_ => true), Is.EqualTo(3));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs one-time cleanup after integration tests by dropping the <c>patients</c> and <c>__migrations</c> collections from the integration database, ensuring a clean state for subsequent test runs.
|
||||
/// </summary>
|
||||
[OneTimeTearDown]
|
||||
public void Teardown()
|
||||
{
|
||||
IntegrationDb.Database.DropCollection("patients");
|
||||
IntegrationDb.Database.DropCollection("__migrations");
|
||||
}
|
||||
public void Teardown()
|
||||
{
|
||||
IntegrationDb.Database.DropCollection("patients");
|
||||
IntegrationDb.Database.DropCollection("__migrations");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the database is detected as outdated by creating a runner and asserting that <c>IsDatabaseUpToDate</c> returns <c>false</c> when using the primary read preference.
|
||||
/// </summary>
|
||||
[Test]
|
||||
[Order(1)]
|
||||
public void IsDatabaseOutdated_ShouldReturnTrue()
|
||||
{
|
||||
var runner = CreateRunner();
|
||||
|
||||
var isUpToDate = runner.IsDatabaseUpToDate(ReadPreference.Primary);
|
||||
|
||||
Assert.That(isUpToDate, Is.False);
|
||||
}
|
||||
[Order(1)]
|
||||
public void IsDatabaseOutdated_ShouldReturnTrue()
|
||||
{
|
||||
var runner = CreateRunner();
|
||||
|
||||
var isUpToDate = runner.IsDatabaseUpToDate(ReadPreference.Primary);
|
||||
|
||||
Assert.That(isUpToDate, Is.False);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that after running the migration update to the latest version, the migration with ID 10 (version 0.1.0) is present among the applied migrations.
|
||||
/// </summary>
|
||||
[Test]
|
||||
[Order(2)]
|
||||
public void AfterUpdateToLatest_MigrationShouldBeApplied()
|
||||
{
|
||||
var runner = CreateRunner();
|
||||
|
||||
runner.UpdateToLatest();
|
||||
var ids = GetAppliedMigrationIds();
|
||||
Assert.That(ids, Does.Contain(10)); // 0.1.0
|
||||
}
|
||||
[Order(2)]
|
||||
public void AfterUpdateToLatest_MigrationShouldBeApplied()
|
||||
{
|
||||
var runner = CreateRunner();
|
||||
|
||||
runner.UpdateToLatest();
|
||||
var ids = GetAppliedMigrationIds();
|
||||
Assert.That(ids, Does.Contain(10)); // 0.1.0
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RunningMigrationsTwice_ShouldNotFail()
|
||||
@@ -132,25 +144,33 @@ public class MongodbMigrationTest
|
||||
}
|
||||
|
||||
// Helpers
|
||||
/// <summary>
|
||||
/// Creates and configures a <see cref="MigrationRunner"/> for executing database migrations, using a locator that scans the assembly containing the patient data update migration.
|
||||
/// </summary>
|
||||
/// <returns>A configured <see cref="MigrationRunner"/> bound to the integration database and the migrations collection.</returns>
|
||||
private MigrationRunner CreateRunner()
|
||||
{
|
||||
var locator = new MigrationLocator();
|
||||
locator.LookForMigrationsInAssembly(typeof(U_0_1_0_UpdateDataPatien).Assembly);
|
||||
return new MigrationRunner(
|
||||
IntegrationDb.Database,
|
||||
collectionName: "__migrations",
|
||||
migrationLocator: locator
|
||||
);
|
||||
}
|
||||
{
|
||||
var locator = new MigrationLocator();
|
||||
locator.LookForMigrationsInAssembly(typeof(U_0_1_0_UpdateDataPatien).Assembly);
|
||||
return new MigrationRunner(
|
||||
IntegrationDb.Database,
|
||||
collectionName: "__migrations",
|
||||
migrationLocator: locator
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the identifiers of all applied migrations from the "__migrations" collection in the integration database.
|
||||
/// </summary>
|
||||
/// <returns>A list of migration identifiers extracted from the "_id" field of each migration document.</returns>
|
||||
private List<int> GetAppliedMigrationIds()
|
||||
{
|
||||
var collection = IntegrationDb.Database.GetCollection<BsonDocument>("__migrations");
|
||||
|
||||
return collection
|
||||
.Find(FilterDefinition<BsonDocument>.Empty)
|
||||
.ToList()
|
||||
.Select(d => d["_id"].AsInt32)
|
||||
.ToList();
|
||||
}
|
||||
{
|
||||
var collection = IntegrationDb.Database.GetCollection<BsonDocument>("__migrations");
|
||||
|
||||
return collection
|
||||
.Find(FilterDefinition<BsonDocument>.Empty)
|
||||
.ToList()
|
||||
.Select(d => d["_id"].AsInt32)
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
@@ -62,21 +62,25 @@ public class ObservationArchiveRepositoryTest
|
||||
private static readonly ObjectId PatientId = ObjectId.GenerateNewId();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's <c>DeleteBeforeDate</c> method removes all patient observations
|
||||
/// dated before the specified cutoff, leaving only a single observation remaining in the collection.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task DeleteBeforeDate()
|
||||
{
|
||||
var filter = Builders<PatientObservation>.Filter.Eq(p => p.PatientId, PatientId);
|
||||
|
||||
var result = await _repository.Collection.FindAsync(filter);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.ToList(), Has.Count.GreaterThan(1));
|
||||
|
||||
await _repository.DeleteBeforeDate(Now);
|
||||
|
||||
var resultDelete = await _repository.Collection.FindAsync(filter);
|
||||
|
||||
Assert.That(resultDelete, Is.Not.Null);
|
||||
Assert.That(resultDelete.ToList(), Has.Count.EqualTo(1));
|
||||
}
|
||||
public async Task DeleteBeforeDate()
|
||||
{
|
||||
var filter = Builders<PatientObservation>.Filter.Eq(p => p.PatientId, PatientId);
|
||||
|
||||
var result = await _repository.Collection.FindAsync(filter);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.ToList(), Has.Count.GreaterThan(1));
|
||||
|
||||
await _repository.DeleteBeforeDate(Now);
|
||||
|
||||
var resultDelete = await _repository.Collection.FindAsync(filter);
|
||||
|
||||
Assert.That(resultDelete, Is.Not.Null);
|
||||
Assert.That(resultDelete.ToList(), Has.Count.EqualTo(1));
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,62 +12,66 @@ namespace adas_core.Test.Repositories;
|
||||
[Category("Integration")]
|
||||
public class PatientArchiveRepositoryTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Performs one-time setup for integration tests by seeding the patient archive collection
|
||||
/// with three predefined <see cref="Patient"/> records after resetting the collection.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var patient1 = new Patient
|
||||
public async Task Init()
|
||||
{
|
||||
UnitString = "PointOfCare",
|
||||
Bed = "bed1",
|
||||
PatientNumber = "patientNumber1",
|
||||
Person = new Person
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var patient1 = new Patient
|
||||
{
|
||||
FirstName = "firstName1",
|
||||
LastName = "lastName1",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
};
|
||||
|
||||
var patient2 = new Patient
|
||||
{
|
||||
UnitString = "PointOfCare",
|
||||
Bed = "bed2",
|
||||
PatientNumber = "patientNumber2",
|
||||
Person = new Person
|
||||
UnitString = "PointOfCare",
|
||||
Bed = "bed1",
|
||||
PatientNumber = "patientNumber1",
|
||||
Person = new Person
|
||||
{
|
||||
FirstName = "firstName1",
|
||||
LastName = "lastName1",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
};
|
||||
|
||||
var patient2 = new Patient
|
||||
{
|
||||
FirstName = "firstName2",
|
||||
LastName = "lastName2",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
};
|
||||
|
||||
var patient3 = new Patient
|
||||
{
|
||||
UnitString = "PointOfCare",
|
||||
Bed = "bed3",
|
||||
PatientNumber = "patientNumber3",
|
||||
Person = new Person
|
||||
UnitString = "PointOfCare",
|
||||
Bed = "bed2",
|
||||
PatientNumber = "patientNumber2",
|
||||
Person = new Person
|
||||
{
|
||||
FirstName = "firstName2",
|
||||
LastName = "lastName2",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
};
|
||||
|
||||
var patient3 = new Patient
|
||||
{
|
||||
FirstName = "firstName3",
|
||||
LastName = "lastName3",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("archive_patient");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("archive_patient");
|
||||
|
||||
_repository = new PatientArchiveRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(patient1);
|
||||
await _repository.InsertOneAsync(patient2);
|
||||
await _repository.InsertOneAsync(patient3);
|
||||
}
|
||||
UnitString = "PointOfCare",
|
||||
Bed = "bed3",
|
||||
PatientNumber = "patientNumber3",
|
||||
Person = new Person
|
||||
{
|
||||
FirstName = "firstName3",
|
||||
LastName = "lastName3",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("archive_patient");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("archive_patient");
|
||||
|
||||
_repository = new PatientArchiveRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(patient1);
|
||||
await _repository.InsertOneAsync(patient2);
|
||||
await _repository.InsertOneAsync(patient3);
|
||||
}
|
||||
|
||||
private PatientArchiveRepository _repository;
|
||||
|
||||
@@ -78,29 +82,40 @@ public class PatientArchiveRepositoryTest
|
||||
|
||||
private IOptions<ApiSettings> _optionsApiSettings;
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the FindByPatientNumber repository method returns null when no record is found for the provided patient number.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByPatientNumber_Not_Find_Return_null()
|
||||
{
|
||||
var result = await _repository.FindByPatientNumber("");
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
public async Task FindByPatientNumber_Not_Find_Return_null()
|
||||
{
|
||||
var result = await _repository.FindByPatientNumber("");
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's FindByPatientNumber method successfully retrieves a patient
|
||||
/// matching the provided patient number, ensuring the returned patient is not null and has
|
||||
/// the expected PatientNumber.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByPatientNumber_Find_Return_Patient()
|
||||
{
|
||||
var result = await _repository.FindByPatientNumber("patientNumber1");
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.PatientNumber, Is.EqualTo("patientNumber1"));
|
||||
}
|
||||
public async Task FindByPatientNumber_Find_Return_Patient()
|
||||
{
|
||||
var result = await _repository.FindByPatientNumber("patientNumber1");
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.PatientNumber, Is.EqualTo("patientNumber1"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's <c>FindAll</c> method returns a non-null list containing the expected number of patient records.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindAll_Return_List_Patients()
|
||||
{
|
||||
var result = await _repository.FindAll();
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Count, Is.EqualTo(3));
|
||||
}
|
||||
public async Task FindAll_Return_List_Patients()
|
||||
{
|
||||
var result = await _repository.FindAll();
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Count, Is.EqualTo(3));
|
||||
}
|
||||
}
|
||||
@@ -17,123 +17,130 @@ public class PatientRepositoryTest
|
||||
{
|
||||
//private static readonly ObjectId id = ObjectId.GenerateNewId();
|
||||
|
||||
/// <summary>
|
||||
/// One-time setup that prepares the integration test database by recreating the
|
||||
/// <c>patient</c>, <c>pointOfCares</c>, <c>units</c>, and <c>list_origin</c> collections
|
||||
/// and seeding them with five patients, their associated point of care, unit, and origin
|
||||
/// list records, then verifies that the initial bulk insert yields exactly five patient
|
||||
/// documents.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var patient1 = new Patient
|
||||
public async Task Init()
|
||||
{
|
||||
Id = PatientId,
|
||||
PatientId = "patientId1",
|
||||
UnitId = _unit1,
|
||||
PointOfCareId = _poc1.Id,
|
||||
PatientNumber = "patientNumber1",
|
||||
Person = new Person
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var patient1 = new Patient
|
||||
{
|
||||
FirstName = "firstName1",
|
||||
LastName = "lastName1",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
},
|
||||
DisTime = Now,
|
||||
Origin = new OptionList
|
||||
Id = PatientId,
|
||||
PatientId = "patientId1",
|
||||
UnitId = _unit1,
|
||||
PointOfCareId = _poc1.Id,
|
||||
PatientNumber = "patientNumber1",
|
||||
Person = new Person
|
||||
{
|
||||
FirstName = "firstName1",
|
||||
LastName = "lastName1",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
},
|
||||
DisTime = Now,
|
||||
Origin = new OptionList
|
||||
{
|
||||
Id = OriginListOptionId,
|
||||
Name = "Urlogy"
|
||||
}
|
||||
};
|
||||
|
||||
var patient2 = new Patient
|
||||
{
|
||||
Id = OriginListOptionId,
|
||||
Name = "Urlogy"
|
||||
}
|
||||
};
|
||||
|
||||
var patient2 = new Patient
|
||||
{
|
||||
UnitId = _unit1,
|
||||
PatientId = "patientId2",
|
||||
PointOfCareId = _poc2.Id,
|
||||
PatientNumber = "patientNumber2",
|
||||
Person = new Person
|
||||
UnitId = _unit1,
|
||||
PatientId = "patientId2",
|
||||
PointOfCareId = _poc2.Id,
|
||||
PatientNumber = "patientNumber2",
|
||||
Person = new Person
|
||||
{
|
||||
FirstName = "firstName2",
|
||||
LastName = "lastName2",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
};
|
||||
|
||||
var patient3 = new Patient
|
||||
{
|
||||
FirstName = "firstName2",
|
||||
LastName = "lastName2",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
};
|
||||
|
||||
var patient3 = new Patient
|
||||
{
|
||||
UnitId = _unit1,
|
||||
PatientId = "patientId3",
|
||||
PointOfCareId = _poc3.Id,
|
||||
PatientNumber = "patientNumber3",
|
||||
Person = new Person
|
||||
UnitId = _unit1,
|
||||
PatientId = "patientId3",
|
||||
PointOfCareId = _poc3.Id,
|
||||
PatientNumber = "patientNumber3",
|
||||
Person = new Person
|
||||
{
|
||||
FirstName = "firstName3",
|
||||
LastName = "lastName3",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
};
|
||||
var patient4 = new Patient
|
||||
{
|
||||
FirstName = "firstName3",
|
||||
LastName = "lastName3",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
};
|
||||
var patient4 = new Patient
|
||||
{
|
||||
UnitId = _pocMoved.UnitId,
|
||||
PatientId = "patientId4",
|
||||
PointOfCareId = _pocMoved.Id,
|
||||
PatientNumber = "patientNumber4",
|
||||
Person = new Person
|
||||
UnitId = _pocMoved.UnitId,
|
||||
PatientId = "patientId4",
|
||||
PointOfCareId = _pocMoved.Id,
|
||||
PatientNumber = "patientNumber4",
|
||||
Person = new Person
|
||||
{
|
||||
FirstName = "firstName4",
|
||||
LastName = "lastName4",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
};
|
||||
var patient5 = new Patient
|
||||
{
|
||||
FirstName = "firstName4",
|
||||
LastName = "lastName4",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
};
|
||||
var patient5 = new Patient
|
||||
{
|
||||
UnitId = _pocPushed.UnitId,
|
||||
PatientId = "patientId5",
|
||||
PointOfCareId = _pocPushed.Id,
|
||||
PatientNumber = "patientNumber5",
|
||||
Person = new Person
|
||||
{
|
||||
FirstName = "firstName5",
|
||||
LastName = "lastName5",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("patient");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("patient");
|
||||
await IntegrationDb.Database.DropCollectionAsync("pointOfCares");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("pointOfCares");
|
||||
await IntegrationDb.Database.DropCollectionAsync("units");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("units");
|
||||
await IntegrationDb.Database.DropCollectionAsync("list_origin");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("list_origin");
|
||||
|
||||
_repository = new PatientRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
_repositoryPoc = new PointOfCareRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
_repositoryUnit = new UnitRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
_repositoryList = new MasterListRepository<OriginList>(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repositoryPoc.InsertOneAsync(_poc1);
|
||||
await _repositoryPoc.InsertOneAsync(_poc2);
|
||||
await _repositoryPoc.InsertOneAsync(_poc3);
|
||||
await _repositoryPoc.InsertOneAsync(_pocMoved);
|
||||
await _repositoryPoc.InsertOneAsync(_pocPushed);
|
||||
await _repository.InsertOneAsync(patient1);
|
||||
await _repository.InsertOneAsync(patient2);
|
||||
await _repository.InsertOneAsync(patient3);
|
||||
await _repository.InsertOneAsync(patient4);
|
||||
await _repository.InsertOneAsync(patient5);
|
||||
await _repositoryUnit.InsertOneAsync(_unit);
|
||||
await _repositoryList.InsertOneAsync(_originList);
|
||||
|
||||
await _repository.FindByPatientNumber("patientNumber1");
|
||||
|
||||
await _repository.InsertManyAsync([patient1, patient2, patient3, patient4, patient5]);
|
||||
Assert.That(await _repository.Collection.CountDocumentsAsync(_ => true), Is.EqualTo(5));
|
||||
}
|
||||
UnitId = _pocPushed.UnitId,
|
||||
PatientId = "patientId5",
|
||||
PointOfCareId = _pocPushed.Id,
|
||||
PatientNumber = "patientNumber5",
|
||||
Person = new Person
|
||||
{
|
||||
FirstName = "firstName5",
|
||||
LastName = "lastName5",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("patient");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("patient");
|
||||
await IntegrationDb.Database.DropCollectionAsync("pointOfCares");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("pointOfCares");
|
||||
await IntegrationDb.Database.DropCollectionAsync("units");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("units");
|
||||
await IntegrationDb.Database.DropCollectionAsync("list_origin");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("list_origin");
|
||||
|
||||
_repository = new PatientRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
_repositoryPoc = new PointOfCareRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
_repositoryUnit = new UnitRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
_repositoryList = new MasterListRepository<OriginList>(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repositoryPoc.InsertOneAsync(_poc1);
|
||||
await _repositoryPoc.InsertOneAsync(_poc2);
|
||||
await _repositoryPoc.InsertOneAsync(_poc3);
|
||||
await _repositoryPoc.InsertOneAsync(_pocMoved);
|
||||
await _repositoryPoc.InsertOneAsync(_pocPushed);
|
||||
await _repository.InsertOneAsync(patient1);
|
||||
await _repository.InsertOneAsync(patient2);
|
||||
await _repository.InsertOneAsync(patient3);
|
||||
await _repository.InsertOneAsync(patient4);
|
||||
await _repository.InsertOneAsync(patient5);
|
||||
await _repositoryUnit.InsertOneAsync(_unit);
|
||||
await _repositoryList.InsertOneAsync(_originList);
|
||||
|
||||
await _repository.FindByPatientNumber("patientNumber1");
|
||||
|
||||
await _repository.InsertManyAsync([patient1, patient2, patient3, patient4, patient5]);
|
||||
Assert.That(await _repository.Collection.CountDocumentsAsync(_ => true), Is.EqualTo(5));
|
||||
}
|
||||
|
||||
private PatientRepository _repository;
|
||||
private PointOfCareRepository _repositoryPoc;
|
||||
@@ -222,136 +229,167 @@ public class PatientRepositoryTest
|
||||
UnitId = ObjectId.GenerateNewId()
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that _repository.FindInActivePoC returns a non-null result containing exactly three inactive PoC entries.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindInActivePoC()
|
||||
{
|
||||
var result = await _repository.FindInActivePoC();
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Count, Is.EqualTo(3));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task FindInInactivePoC()
|
||||
{
|
||||
var result = await _repository.FindInInactivePoC();
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Count, Is.EqualTo(2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task FindById_Find_Return_Patient()
|
||||
{
|
||||
var result = await _repository.FindById(PatientId);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.PatientNumber, Is.EqualTo("patientNumber1"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task FindByPatientNumber_Not_Find_Return_Patient()
|
||||
{
|
||||
var result = await _repository.FindByPatientNumber("");
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task FindByPatientNumber_Find_Return_Patient()
|
||||
{
|
||||
var result = await _repository.FindByPatientNumber("patientNumber1");
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.PatientNumber, Is.EqualTo("patientNumber1"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task FindAll_Return_List_Patients()
|
||||
{
|
||||
var result = await _repository.FindAll();
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Has.Count.EqualTo(5));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Update_with_base_UpdateOneAsync()
|
||||
{
|
||||
var patient = new Patient
|
||||
public async Task FindInActivePoC()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
UnitString = "PointOfCare",
|
||||
Bed = "bed",
|
||||
PatientNumber = "patientNumber",
|
||||
Person = new Person
|
||||
{
|
||||
FirstName = "firstName",
|
||||
LastName = "lastName",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
};
|
||||
|
||||
var patientUpdate = new Patient
|
||||
{
|
||||
Id = patient.Id,
|
||||
UnitString = "PointOfCare",
|
||||
Bed = "bed",
|
||||
PatientNumber = "patientNumberUpdate",
|
||||
Person = new Person
|
||||
{
|
||||
FirstName = "firstName",
|
||||
LastName = "lastName",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(patient);
|
||||
|
||||
var result = await _repository.FindByPatientNumber("patientNumberUpdate");
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
|
||||
await _repository.Update(patientUpdate);
|
||||
|
||||
var resultUpdate = await _repository.FindByPatientNumber("patientNumberUpdate");
|
||||
|
||||
Assert.That(resultUpdate, Is.Not.Null);
|
||||
Assert.That(resultUpdate.PatientNumber, Is.EqualTo("patientNumberUpdate"));
|
||||
|
||||
await _repository.Delete(patient.Id);
|
||||
}
|
||||
var result = await _repository.FindInActivePoC();
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Count, Is.EqualTo(3));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that _repository.FindInInactivePoC() returns a non-null collection containing exactly two inactive PoC records.
|
||||
/// </summary>
|
||||
/// <returns>A Task representing the asynchronous test execution.</returns>
|
||||
[Test]
|
||||
public async Task Delete()
|
||||
{
|
||||
var patientDelete = new Patient
|
||||
public async Task FindInInactivePoC()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
UnitString = "PointOfCare",
|
||||
Bed = "bedDelete",
|
||||
PatientNumber = "patientNumberDelete",
|
||||
Person = new Person
|
||||
var result = await _repository.FindInInactivePoC();
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Count, Is.EqualTo(2));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that FindById returns the expected <c>Patient</c> when a valid patient identifier is provided, ensuring the result is not null and the <c>PatientNumber</c> matches the expected value.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindById_Find_Return_Patient()
|
||||
{
|
||||
var result = await _repository.FindById(PatientId);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.PatientNumber, Is.EqualTo("patientNumber1"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's <c>FindByPatientNumber</c> method returns <c>null</c> when invoked with an empty patient number, confirming the not-found scenario for blank input.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByPatientNumber_Not_Find_Return_Patient()
|
||||
{
|
||||
var result = await _repository.FindByPatientNumber("");
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's <c>FindByPatientNumber</c> method successfully retrieves
|
||||
/// a patient when called with a valid patient number, returning a non-null result
|
||||
/// with a matching <c>PatientNumber</c>.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByPatientNumber_Find_Return_Patient()
|
||||
{
|
||||
var result = await _repository.FindByPatientNumber("patientNumber1");
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.PatientNumber, Is.EqualTo("patientNumber1"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's <c>FindAll</c> method returns a non-null list containing all expected patient records (five entries).
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindAll_Return_List_Patients()
|
||||
{
|
||||
var result = await _repository.FindAll();
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Has.Count.EqualTo(5));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's <c>Update</c> method successfully updates an existing patient record
|
||||
/// by confirming that the updated <c>PatientNumber</c> becomes findable after the update, while ensuring
|
||||
/// the new value is not present prior to the update operation. Also validates that the updated record
|
||||
/// is persisted with the modified value and that the patient can be cleaned up via <c>Delete</c>.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Update_with_base_UpdateOneAsync()
|
||||
{
|
||||
var patient = new Patient
|
||||
{
|
||||
FirstName = "firstName",
|
||||
LastName = "lastName",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
};
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
UnitString = "PointOfCare",
|
||||
Bed = "bed",
|
||||
PatientNumber = "patientNumber",
|
||||
Person = new Person
|
||||
{
|
||||
FirstName = "firstName",
|
||||
LastName = "lastName",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
};
|
||||
|
||||
var patientUpdate = new Patient
|
||||
{
|
||||
Id = patient.Id,
|
||||
UnitString = "PointOfCare",
|
||||
Bed = "bed",
|
||||
PatientNumber = "patientNumberUpdate",
|
||||
Person = new Person
|
||||
{
|
||||
FirstName = "firstName",
|
||||
LastName = "lastName",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(patient);
|
||||
|
||||
var result = await _repository.FindByPatientNumber("patientNumberUpdate");
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
|
||||
await _repository.Update(patientUpdate);
|
||||
|
||||
var resultUpdate = await _repository.FindByPatientNumber("patientNumberUpdate");
|
||||
|
||||
Assert.That(resultUpdate, Is.Not.Null);
|
||||
Assert.That(resultUpdate.PatientNumber, Is.EqualTo("patientNumberUpdate"));
|
||||
|
||||
await _repository.Delete(patient.Id);
|
||||
}
|
||||
|
||||
await _repository.InsertOneAsync(patientDelete);
|
||||
|
||||
var result = await _repository.FindByPatientNumber("patientNumberDelete");
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
|
||||
await _repository.Delete(patientDelete.Id);
|
||||
|
||||
var resultDelete = await _repository.FindByPatientNumber("patientNumberDelete");
|
||||
|
||||
Assert.That(resultDelete, Is.Null);
|
||||
}
|
||||
/// <summary>
|
||||
/// Verifies that a patient can be successfully deleted from the repository by inserting a patient,
|
||||
/// confirming it exists, deleting it, and then confirming it is no longer retrievable.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Delete()
|
||||
{
|
||||
var patientDelete = new Patient
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
UnitString = "PointOfCare",
|
||||
Bed = "bedDelete",
|
||||
PatientNumber = "patientNumberDelete",
|
||||
Person = new Person
|
||||
{
|
||||
FirstName = "firstName",
|
||||
LastName = "lastName",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(patientDelete);
|
||||
|
||||
var result = await _repository.FindByPatientNumber("patientNumberDelete");
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
|
||||
await _repository.Delete(patientDelete.Id);
|
||||
|
||||
var resultDelete = await _repository.FindByPatientNumber("patientNumberDelete");
|
||||
|
||||
Assert.That(resultDelete, Is.Null);
|
||||
}
|
||||
|
||||
|
||||
// [Test]
|
||||
@@ -390,25 +428,29 @@ public class PatientRepositoryTest
|
||||
// await _repository.Delete(patient.Id);
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Tests that the attending doctor of a point of care entry can be successfully updated with a new doctor.
|
||||
/// Verifies that after the update, the entry retrieved by point of care reflects the new attending doctor's information.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task UpdateAttendingDoctor()
|
||||
{
|
||||
var doctor = new Person
|
||||
public async Task UpdateAttendingDoctor()
|
||||
{
|
||||
FirstName = "firstNameDoctor2",
|
||||
LastName = "lastNameDoctor2",
|
||||
Gender = PatientEnum.Gender.Female
|
||||
};
|
||||
|
||||
var result = await _repository.FindByPointOfCare(_poc1.Id);
|
||||
|
||||
await _repository.UpdateAttendingDoctor(result.First().Id, doctor);
|
||||
|
||||
var resultUpdate = await _repository.FindByPointOfCare(_poc1.Id);
|
||||
|
||||
Assert.That(resultUpdate, Is.Not.Null);
|
||||
Assert.That(resultUpdate.First().AttendingDoctor?.FirstName, Is.EqualTo("firstNameDoctor2"));
|
||||
}
|
||||
var doctor = new Person
|
||||
{
|
||||
FirstName = "firstNameDoctor2",
|
||||
LastName = "lastNameDoctor2",
|
||||
Gender = PatientEnum.Gender.Female
|
||||
};
|
||||
|
||||
var result = await _repository.FindByPointOfCare(_poc1.Id);
|
||||
|
||||
await _repository.UpdateAttendingDoctor(result.First().Id, doctor);
|
||||
|
||||
var resultUpdate = await _repository.FindByPointOfCare(_poc1.Id);
|
||||
|
||||
Assert.That(resultUpdate, Is.Not.Null);
|
||||
Assert.That(resultUpdate.First().AttendingDoctor?.FirstName, Is.EqualTo("firstNameDoctor2"));
|
||||
}
|
||||
|
||||
// [Test]
|
||||
// public async Task UpdatePatientData_UpdatePatientNumber_true()
|
||||
@@ -577,13 +619,16 @@ public class PatientRepositoryTest
|
||||
// await _repository.Delete(patient1.Id);
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that _repository.FindByPatientId returns <c>null</c> when no patient is found for the provided patient identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByPatientId_Not_Find_Return_Patient()
|
||||
{
|
||||
var result = await _repository.FindByPatientId("");
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
public async Task FindByPatientId_Not_Find_Return_Patient()
|
||||
{
|
||||
var result = await _repository.FindByPatientId("");
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
// [Test]
|
||||
// public async Task FindByPatientId_Find_Return_Patient()
|
||||
@@ -594,31 +639,40 @@ public class PatientRepositoryTest
|
||||
// Assert.That(result.PatientNumber, Is.EqualTo("patientNumber1"));
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository returns a non-null and non-empty collection of patients when searching by the identifier of an existing point of care.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByPointOfCare_Find_Return_Patients()
|
||||
{
|
||||
var result = await _repository.FindByPointOfCare(_poc1.Id);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Not.Empty);
|
||||
// Assert.That(result.Count.Equals(1));
|
||||
}
|
||||
public async Task FindByPointOfCare_Find_Return_Patients()
|
||||
{
|
||||
var result = await _repository.FindByPointOfCare(_poc1.Id);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Not.Empty);
|
||||
// Assert.That(result.Count.Equals(1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that _repository.FindByPointOfCare returns a non-null empty collection when no patients match the provided point of care identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByPointOfCare_Not_Find_Return_Patients()
|
||||
{
|
||||
var result = await _repository.FindByPointOfCare(ObjectId.GenerateNewId());
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
public async Task FindByPointOfCare_Not_Find_Return_Patients()
|
||||
{
|
||||
var result = await _repository.FindByPointOfCare(ObjectId.GenerateNewId());
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository returns a non-null and non-empty collection of discharged patients when calling <c>FindDischargedPatients</c>.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindDischargedPatients_Find_Return_Patients()
|
||||
{
|
||||
var result = await _repository.FindDischargedPatients();
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Not.Empty);
|
||||
}
|
||||
public async Task FindDischargedPatients_Find_Return_Patients()
|
||||
{
|
||||
var result = await _repository.FindDischargedPatients();
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Not.Empty);
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,9 @@ namespace adas_core.Test.Repositories;
|
||||
[Category("Integration")]
|
||||
public class PoCMappingRepositoryTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Performs one-time setup for integration tests by seeding the "mappings" collection with a sample <see cref="PoCMapping"/> document, where a single point of care is mapped from an original value to a new one across eleven bed entries, and initializing the <see cref="PoCMappingRepository"/> against the integration database.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
@@ -22,16 +25,16 @@ public class PoCMappingRepositoryTest
|
||||
Beds =
|
||||
[
|
||||
new List<string> { "bed1", "bed 1" },
|
||||
new List<string> { "bed2", "bed 2" },
|
||||
new List<string> { "bed3", "bed 3" },
|
||||
new List<string> { "bed4", "bed 4" },
|
||||
new List<string> { "bed5", "bed 5" },
|
||||
new List<string> { "bed6", "bed 6" },
|
||||
new List<string> { "bed7", "bed 7" },
|
||||
new List<string> { "bed8", "bed 8" },
|
||||
new List<string> { "bed9", "bed 9" },
|
||||
new List<string> { "bed10", "bed 10" },
|
||||
new List<string> { "bed11", "bed 11" }
|
||||
new List<string> { "bed2", "bed 2" },
|
||||
new List<string> { "bed3", "bed 3" },
|
||||
new List<string> { "bed4", "bed 4" },
|
||||
new List<string> { "bed5", "bed 5" },
|
||||
new List<string> { "bed6", "bed 6" },
|
||||
new List<string> { "bed7", "bed 7" },
|
||||
new List<string> { "bed8", "bed 8" },
|
||||
new List<string> { "bed9", "bed 9" },
|
||||
new List<string> { "bed10", "bed 10" },
|
||||
new List<string> { "bed11", "bed 11" }
|
||||
]
|
||||
};
|
||||
|
||||
@@ -58,6 +61,9 @@ public class PoCMappingRepositoryTest
|
||||
private IOptions<ApiSettings> _optionsApiSettings;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that finding a mapping by the key "PV1" returns a non-null result containing point of care entries with at least one associated bed.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByKey_Find_Return_Mapping()
|
||||
{
|
||||
@@ -68,6 +74,9 @@ public class PoCMappingRepositoryTest
|
||||
Assert.That(result.PointOfCares[0].Beds, Has.Count.GreaterThan(0));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's FindByKey method returns null when the provided key does not correspond to an existing entity, confirming the not-found behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByKey_Not_Find_Return_Mapping()
|
||||
{
|
||||
|
||||
@@ -11,18 +11,21 @@ namespace adas_core.Test.Repositories;
|
||||
[TestFixture]
|
||||
public class PoCSettingsRepositoryTest
|
||||
{
|
||||
/// <summary>
|
||||
/// One-time setup that prepares the integration test environment by resetting the PoC settings collection in the integration database, seeding it with test data, and instantiating the <see cref="PoCSettingsRepository"/> used by the test fixture.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync(_apiSettings.PoCSettings);
|
||||
await IntegrationDb.Database.CreateCollectionAsync(_apiSettings.PoCSettings);
|
||||
|
||||
_repository = new PoCSettingsRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(TestPoCSettings);
|
||||
}
|
||||
public async Task Init()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync(_apiSettings.PoCSettings);
|
||||
await IntegrationDb.Database.CreateCollectionAsync(_apiSettings.PoCSettings);
|
||||
|
||||
_repository = new PoCSettingsRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(TestPoCSettings);
|
||||
}
|
||||
|
||||
private PoCSettingsRepository _repository;
|
||||
|
||||
@@ -42,76 +45,92 @@ public class PoCSettingsRepositoryTest
|
||||
PatientLocation = TestLocation
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that calling the Delete method with an existing PoCSettings identifier removes the corresponding record from the repository, resulting in a null lookup via FindById.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Delete_WhenCalled_ShouldRemovePoCSettings()
|
||||
{
|
||||
// Arrange
|
||||
var newObjectId = ObjectId.GenerateNewId();
|
||||
var newPoCSettings = new PoCSettings
|
||||
public async Task Delete_WhenCalled_ShouldRemovePoCSettings()
|
||||
{
|
||||
Id = newObjectId,
|
||||
PatientLocation = new PatientLocation("poc2", "bed2")
|
||||
};
|
||||
await _repository.InsertOneAsync(newPoCSettings);
|
||||
|
||||
// Act
|
||||
await _repository.Delete(newObjectId);
|
||||
|
||||
// Assert
|
||||
var result = await _repository.FindById(newObjectId);
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
// Arrange
|
||||
var newObjectId = ObjectId.GenerateNewId();
|
||||
var newPoCSettings = new PoCSettings
|
||||
{
|
||||
Id = newObjectId,
|
||||
PatientLocation = new PatientLocation("poc2", "bed2")
|
||||
};
|
||||
await _repository.InsertOneAsync(newPoCSettings);
|
||||
|
||||
// Act
|
||||
await _repository.Delete(newObjectId);
|
||||
|
||||
// Assert
|
||||
var result = await _repository.FindById(newObjectId);
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's <c>FindAll</c> method returns a non-null and non-empty collection of PoC settings.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindAll_WhenCalled_ShouldReturnAllPoCSettings()
|
||||
{
|
||||
// Act
|
||||
var result = await _repository.FindAll();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Not.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task FindById_WhenCalled_ShouldReturnPoCSettings()
|
||||
{
|
||||
// Act
|
||||
var result = await _repository.FindById(TestObjectId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result?.Id, Is.EqualTo(TestObjectId));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task FindByLocation_WhenCalled_ShouldReturnPoCSettings()
|
||||
{
|
||||
// Act
|
||||
var result = await _repository.FindByLocation(TestLocation);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result?.PatientLocation, Is.EqualTo(TestLocation));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Update_WhenCalled_ShouldUpdatePoCSettings()
|
||||
{
|
||||
// Arrange
|
||||
var updatedPoCSettings = new PoCSettings
|
||||
public async Task FindAll_WhenCalled_ShouldReturnAllPoCSettings()
|
||||
{
|
||||
Id = TestObjectId,
|
||||
PatientLocation = new PatientLocation("POC3", "Bed3")
|
||||
};
|
||||
// Act
|
||||
var result = await _repository.FindAll();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Not.Empty);
|
||||
}
|
||||
|
||||
// Act
|
||||
await _repository.Update(updatedPoCSettings);
|
||||
/// <summary>
|
||||
/// Tests that FindById returns a non-null PoC settings object whose identifier matches the requested value.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindById_WhenCalled_ShouldReturnPoCSettings()
|
||||
{
|
||||
// Act
|
||||
var result = await _repository.FindById(TestObjectId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result?.Id, Is.EqualTo(TestObjectId));
|
||||
}
|
||||
|
||||
// Assert
|
||||
var result = await _repository.FindById(TestObjectId);
|
||||
Assert.That(result, Is.Not.Null);
|
||||
//Assert.That(result?.PatientLocation?.PointOfCare, Is.EqualTo("POC3"));
|
||||
Assert.That(result?.PatientLocation?.Bed, Is.EqualTo("Bed3"));
|
||||
}
|
||||
/// <summary>
|
||||
/// Verifies that _repository.FindByLocation returns a PoC settings object matching the requested patient location.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByLocation_WhenCalled_ShouldReturnPoCSettings()
|
||||
{
|
||||
// Act
|
||||
var result = await _repository.FindByLocation(TestLocation);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result?.PatientLocation, Is.EqualTo(TestLocation));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository correctly updates an existing PoCSettings entity, specifically ensuring that the associated PatientLocation properties (such as Bed) are persisted after the update operation.
|
||||
/// </summary>
|
||||
/// <returns>A task that represents the asynchronous test execution.</returns>
|
||||
[Test]
|
||||
public async Task Update_WhenCalled_ShouldUpdatePoCSettings()
|
||||
{
|
||||
// Arrange
|
||||
var updatedPoCSettings = new PoCSettings
|
||||
{
|
||||
Id = TestObjectId,
|
||||
PatientLocation = new PatientLocation("POC3", "Bed3")
|
||||
};
|
||||
|
||||
// Act
|
||||
await _repository.Update(updatedPoCSettings);
|
||||
|
||||
// Assert
|
||||
var result = await _repository.FindById(TestObjectId);
|
||||
Assert.That(result, Is.Not.Null);
|
||||
//Assert.That(result?.PatientLocation?.PointOfCare, Is.EqualTo("POC3"));
|
||||
Assert.That(result?.PatientLocation?.Bed, Is.EqualTo("Bed3"));
|
||||
}
|
||||
}
|
||||
@@ -14,168 +14,199 @@ namespace adas_core.Test.Repositories;
|
||||
[Category("Integration")]
|
||||
public class PointOfCareRepositoryTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Performs one-time setup for integration tests by initializing mock dependencies and resetting the
|
||||
/// "pointOfCares" MongoDB collection before instantiating the <see cref="PointOfCareRepository"/>.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(new ApiSettings());
|
||||
_mockCollection = new Mock<IMongoCollection<PointOfCare>>();
|
||||
_mockDatabase = new Mock<IMongoDatabase>();
|
||||
_mockDatabase.Setup(db => db.GetCollection<PointOfCare>(It.IsAny<string>(), null))
|
||||
.Returns(_mockCollection.Object);
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("pointOfCares");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("pointOfCares");
|
||||
_repository = new PointOfCareRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
}
|
||||
public async Task Init()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(new ApiSettings());
|
||||
_mockCollection = new Mock<IMongoCollection<PointOfCare>>();
|
||||
_mockDatabase = new Mock<IMongoDatabase>();
|
||||
_mockDatabase.Setup(db => db.GetCollection<PointOfCare>(It.IsAny<string>(), null))
|
||||
.Returns(_mockCollection.Object);
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("pointOfCares");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("pointOfCares");
|
||||
_repository = new PointOfCareRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
}
|
||||
|
||||
private PointOfCareRepository _repository;
|
||||
private Mock<IMongoCollection<PointOfCare>> _mockCollection;
|
||||
private Mock<IMongoDatabase> _mockDatabase;
|
||||
private IOptions<ApiSettings> _optionsApiSettings;
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that InsertOneAsync successfully inserts a valid point of care into the repository and that the record can be retrieved by its identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task InsertOneAsync_ValidPointOfCare_InsertsSuccessfully()
|
||||
{
|
||||
// Arrange
|
||||
var pointOfCare = TestUtilities.CreateValidPointOfCare();
|
||||
|
||||
// Act
|
||||
await _repository.InsertOneAsync(pointOfCare);
|
||||
|
||||
// Assert
|
||||
var insertedPointOfCare = await _repository.FindById(pointOfCare.Id);
|
||||
Assert.That(insertedPointOfCare, Is.Not.Null, "Inserted point of care should not be null");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Delete_ValidId_DeletesSuccessfully()
|
||||
{
|
||||
var pointOfCare = TestUtilities.CreateValidPointOfCare();
|
||||
await _repository.InsertOneAsync(pointOfCare);
|
||||
|
||||
await _repository.Delete(pointOfCare.Id);
|
||||
|
||||
// Assert
|
||||
var deletedPointOfCare = await _repository.FindById(pointOfCare.Id);
|
||||
Assert.That(deletedPointOfCare, Is.Null, "Deleted point of care should be null");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Update_ValidPointOfCare_UpdatesSuccessfully()
|
||||
{
|
||||
// Arrange
|
||||
var originalPointOfCare = TestUtilities.CreateValidPointOfCare();
|
||||
await _repository.InsertOneAsync(originalPointOfCare); // Insert the original point of care
|
||||
|
||||
// Modify some properties to update
|
||||
originalPointOfCare.Room = "Updated Room";
|
||||
originalPointOfCare.Bed = "Updated Bed";
|
||||
|
||||
// Act
|
||||
await _repository.Update(originalPointOfCare); // Update the point of care
|
||||
|
||||
// Retrieve the updated point of care
|
||||
var updatedPointOfCare = await _repository.FindById(originalPointOfCare.Id);
|
||||
|
||||
// Assert
|
||||
Assert.That(updatedPointOfCare, Is.Not.Null, "Updated point of care should not be null");
|
||||
Assert.That(updatedPointOfCare?.Room, Is.EqualTo(originalPointOfCare.Room), "Room should be updated");
|
||||
Assert.That(updatedPointOfCare?.Bed, Is.EqualTo(originalPointOfCare.Bed), "Bed should be updated");
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public async Task FindById_ExistingId_ReturnsPointOfCare()
|
||||
{
|
||||
// Arrange
|
||||
var pointOfCareId = ObjectId.GenerateNewId();
|
||||
var expectedPointOfCare = TestUtilities.CreateValidPointOfCare();
|
||||
expectedPointOfCare.Id = pointOfCareId;
|
||||
|
||||
// Insert a PointOfCare document into the database
|
||||
await _repository.InsertOneAsync(expectedPointOfCare);
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindById(pointOfCareId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null, "Returned PointOfCare should not be null");
|
||||
Assert.That(result!.Id, Is.EqualTo(expectedPointOfCare.Id), "Returned PointOfCare should have the expected ID");
|
||||
// Add additional assertions to compare other properties if needed
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task FindByUnitAndStatus_ExistingUnitAndStatus_ReturnsMatchingPointOfCares()
|
||||
{
|
||||
// Arrange
|
||||
var expectedPointOfCare = TestUtilities.CreateValidPointOfCare();
|
||||
|
||||
// Insert PointOfCare documents into the database with the specified unit ID and status
|
||||
|
||||
await _repository.InsertOneAsync(expectedPointOfCare);
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindByUnitAndStatus(expectedPointOfCare.UnitId, expectedPointOfCare.Status);
|
||||
|
||||
var resultList = result.ToList();
|
||||
// Assert
|
||||
Assert.That(resultList, Is.Not.Null, "Returned collection should not be null");
|
||||
Assert.That(resultList.First().Id, Is.EqualTo(expectedPointOfCare.Id),
|
||||
"Returned collection should contain expected PointOfCare object");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task FindByRoom_ValidRoom_ReturnsMatchingPointOfCares()
|
||||
{
|
||||
var expectedPointOfCare = TestUtilities.CreateValidPointOfCare();
|
||||
await _repository.InsertOneAsync(expectedPointOfCare);
|
||||
|
||||
// Act
|
||||
if (expectedPointOfCare.Unit != null)
|
||||
public async Task InsertOneAsync_ValidPointOfCare_InsertsSuccessfully()
|
||||
{
|
||||
var result = await _repository.FindByRoom(expectedPointOfCare.Room);
|
||||
// Arrange
|
||||
var pointOfCare = TestUtilities.CreateValidPointOfCare();
|
||||
|
||||
// Act
|
||||
await _repository.InsertOneAsync(pointOfCare);
|
||||
|
||||
// Assert
|
||||
var insertedPointOfCare = await _repository.FindById(pointOfCare.Id);
|
||||
Assert.That(insertedPointOfCare, Is.Not.Null, "Inserted point of care should not be null");
|
||||
}
|
||||
|
||||
var resultList = result?.ToList();
|
||||
/// <summary>
|
||||
/// Verifies that the Delete method successfully removes a point of care from the repository when given a valid identifier.
|
||||
/// Inserts a point of care, deletes it by its identifier, and asserts that the entity can no longer be retrieved.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Delete_ValidId_DeletesSuccessfully()
|
||||
{
|
||||
var pointOfCare = TestUtilities.CreateValidPointOfCare();
|
||||
await _repository.InsertOneAsync(pointOfCare);
|
||||
|
||||
await _repository.Delete(pointOfCare.Id);
|
||||
|
||||
// Assert
|
||||
var deletedPointOfCare = await _repository.FindById(pointOfCare.Id);
|
||||
Assert.That(deletedPointOfCare, Is.Null, "Deleted point of care should be null");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="PointOfCare"/> entities can be updated successfully when valid data is provided, ensuring that modified properties such as <c>Room</c> and <c>Bed</c> are persisted and retrievable after the update operation.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Update_ValidPointOfCare_UpdatesSuccessfully()
|
||||
{
|
||||
// Arrange
|
||||
var originalPointOfCare = TestUtilities.CreateValidPointOfCare();
|
||||
await _repository.InsertOneAsync(originalPointOfCare); // Insert the original point of care
|
||||
|
||||
// Modify some properties to update
|
||||
originalPointOfCare.Room = "Updated Room";
|
||||
originalPointOfCare.Bed = "Updated Bed";
|
||||
|
||||
// Act
|
||||
await _repository.Update(originalPointOfCare); // Update the point of care
|
||||
|
||||
// Retrieve the updated point of care
|
||||
var updatedPointOfCare = await _repository.FindById(originalPointOfCare.Id);
|
||||
|
||||
// Assert
|
||||
Assert.That(updatedPointOfCare, Is.Not.Null, "Updated point of care should not be null");
|
||||
Assert.That(updatedPointOfCare?.Room, Is.EqualTo(originalPointOfCare.Room), "Room should be updated");
|
||||
Assert.That(updatedPointOfCare?.Bed, Is.EqualTo(originalPointOfCare.Bed), "Bed should be updated");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's <c>FindById</c> method returns the correct <c>PointOfCare</c> document when queried with an existing identifier, by inserting a document and asserting that the retrieved entity matches the expected one.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindById_ExistingId_ReturnsPointOfCare()
|
||||
{
|
||||
// Arrange
|
||||
var pointOfCareId = ObjectId.GenerateNewId();
|
||||
var expectedPointOfCare = TestUtilities.CreateValidPointOfCare();
|
||||
expectedPointOfCare.Id = pointOfCareId;
|
||||
|
||||
// Insert a PointOfCare document into the database
|
||||
await _repository.InsertOneAsync(expectedPointOfCare);
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindById(pointOfCareId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null, "Returned PointOfCare should not be null");
|
||||
Assert.That(result!.Id, Is.EqualTo(expectedPointOfCare.Id), "Returned PointOfCare should have the expected ID");
|
||||
// Add additional assertions to compare other properties if needed
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that FindByUnitAndStatus returns the matching <c>PointOfCare</c> documents when queried with an existing unit identifier and status.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByUnitAndStatus_ExistingUnitAndStatus_ReturnsMatchingPointOfCares()
|
||||
{
|
||||
// Arrange
|
||||
var expectedPointOfCare = TestUtilities.CreateValidPointOfCare();
|
||||
|
||||
// Insert PointOfCare documents into the database with the specified unit ID and status
|
||||
|
||||
await _repository.InsertOneAsync(expectedPointOfCare);
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindByUnitAndStatus(expectedPointOfCare.UnitId, expectedPointOfCare.Status);
|
||||
|
||||
var resultList = result.ToList();
|
||||
// Assert
|
||||
Assert.That(resultList, Is.Not.Null, "Returned collection should not be null");
|
||||
|
||||
Assert.That(resultList?.Any(p => p.Id == expectedPointOfCare.Id), Is.True,
|
||||
Assert.That(resultList.First().Id, Is.EqualTo(expectedPointOfCare.Id),
|
||||
"Returned collection should contain expected PointOfCare object");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that <c>FindByRoom</c> returns the matching <c>PointOfCare</c> when a valid room is provided.
|
||||
/// Inserts a valid <c>PointOfCare</c> into the repository and verifies the search by room returns a non-null collection
|
||||
/// containing the expected entity. Assertions are only executed when the inserted <c>PointOfCare</c> has a non-null <c>Unit</c>.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByBed_ValidBed_ReturnsMatchingPointOfCares()
|
||||
{
|
||||
var expectedPointOfCare = TestUtilities.CreateValidPointOfCare();
|
||||
await _repository.InsertOneAsync(expectedPointOfCare);
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindByBed(expectedPointOfCare.Bed);
|
||||
|
||||
// Convert the result to a list or an array
|
||||
var resultList = result?.ToList();
|
||||
|
||||
// Assert
|
||||
Assert.That(resultList, Is.Not.Null, "Returned collection should not be null");
|
||||
|
||||
// Check if the expected point of care is contained within the result
|
||||
Assert.That(resultList?.First().Bed, Is.EqualTo(expectedPointOfCare.Bed),
|
||||
"Returned collection should contain expected PointOfCare object");
|
||||
}
|
||||
public async Task FindByRoom_ValidRoom_ReturnsMatchingPointOfCares()
|
||||
{
|
||||
var expectedPointOfCare = TestUtilities.CreateValidPointOfCare();
|
||||
await _repository.InsertOneAsync(expectedPointOfCare);
|
||||
|
||||
// Act
|
||||
if (expectedPointOfCare.Unit != null)
|
||||
{
|
||||
var result = await _repository.FindByRoom(expectedPointOfCare.Room);
|
||||
|
||||
var resultList = result?.ToList();
|
||||
|
||||
// Assert
|
||||
Assert.That(resultList, Is.Not.Null, "Returned collection should not be null");
|
||||
|
||||
Assert.That(resultList?.Any(p => p.Id == expectedPointOfCare.Id), Is.True,
|
||||
"Returned collection should contain expected PointOfCare object");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository returns the matching PointOfCare when queried with a valid bed identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetAll_ReturnsAllPointOfCares()
|
||||
{
|
||||
var poc = TestUtilities.CreateValidPointOfCare();
|
||||
await _repository.InsertOneAsync(poc);
|
||||
public async Task FindByBed_ValidBed_ReturnsMatchingPointOfCares()
|
||||
{
|
||||
var expectedPointOfCare = TestUtilities.CreateValidPointOfCare();
|
||||
await _repository.InsertOneAsync(expectedPointOfCare);
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindByBed(expectedPointOfCare.Bed);
|
||||
|
||||
// Convert the result to a list or an array
|
||||
var resultList = result?.ToList();
|
||||
|
||||
// Assert
|
||||
Assert.That(resultList, Is.Not.Null, "Returned collection should not be null");
|
||||
|
||||
// Check if the expected point of care is contained within the result
|
||||
Assert.That(resultList?.First().Bed, Is.EqualTo(expectedPointOfCare.Bed),
|
||||
"Returned collection should contain expected PointOfCare object");
|
||||
}
|
||||
|
||||
var result = await _repository.GetAll();
|
||||
|
||||
var resultList = result?.ToList();
|
||||
// Assert
|
||||
Assert.That(resultList?.Any(p => p.Id == poc.Id), Is.True,
|
||||
"Returned collection should contain the expected PointOfCare object with the specified Id");
|
||||
}
|
||||
/// <summary>
|
||||
/// Verifies that the <c>GetAll</c> repository method returns all stored <c>PointOfCare</c> entries, including a newly inserted one identified by its assigned Id.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetAll_ReturnsAllPointOfCares()
|
||||
{
|
||||
var poc = TestUtilities.CreateValidPointOfCare();
|
||||
await _repository.InsertOneAsync(poc);
|
||||
|
||||
var result = await _repository.GetAll();
|
||||
|
||||
var resultList = result?.ToList();
|
||||
// Assert
|
||||
Assert.That(resultList?.Any(p => p.Id == poc.Id), Is.True,
|
||||
"Returned collection should contain the expected PointOfCare object with the specified Id");
|
||||
}
|
||||
}
|
||||
@@ -23,122 +23,140 @@ public class PumpAlarmEventRepositoryTest
|
||||
// -------------------------------------------------------------------
|
||||
// INIT – Setup inicial de colección con índices y datos de prueba
|
||||
// -------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Performs one-time integration test setup for the pump alarm event repository by configuring API settings,
|
||||
/// resetting the dedicated MongoDB collection, creating required indexes, and seeding it with three initial
|
||||
/// alarm events covering both Device and DeviceB across attention and occlusion
|
||||
/// alarm types. Verifies that exactly three documents are present after seeding.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
_apiSettings = Options.Create(new ApiSettings
|
||||
public async Task Init()
|
||||
{
|
||||
PumpAlarmEvent = "pump_alarm_event"
|
||||
});
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("pump_alarm_event");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("pump_alarm_event");
|
||||
|
||||
_repo = new PumpAlarmEventRepository(
|
||||
_apiSettings,
|
||||
IntegrationDb.Database
|
||||
);
|
||||
|
||||
await _repo.CreateIndexes();
|
||||
|
||||
var initialEvents = new List<PumpAlarmEvent>
|
||||
{
|
||||
new()
|
||||
_apiSettings = Options.Create(new ApiSettings
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = DeviceA,
|
||||
PatientId = PatientId,
|
||||
AlarmType = PumpEnum.AlarmType.Attention,
|
||||
Time = Now.AddSeconds(-1)
|
||||
},
|
||||
new()
|
||||
PumpAlarmEvent = "pump_alarm_event"
|
||||
});
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("pump_alarm_event");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("pump_alarm_event");
|
||||
|
||||
_repo = new PumpAlarmEventRepository(
|
||||
_apiSettings,
|
||||
IntegrationDb.Database
|
||||
);
|
||||
|
||||
await _repo.CreateIndexes();
|
||||
|
||||
var initialEvents = new List<PumpAlarmEvent>
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = DeviceA,
|
||||
PatientId = PatientId,
|
||||
AlarmType = PumpEnum.AlarmType.Occlusion,
|
||||
Time = Now.AddSeconds(-3)
|
||||
},
|
||||
new()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = DeviceB,
|
||||
PatientId = PatientId,
|
||||
AlarmType = PumpEnum.AlarmType.Occlusion,
|
||||
Time = Now.AddSeconds(-2)
|
||||
}
|
||||
};
|
||||
|
||||
await IntegrationDb.Database
|
||||
.GetCollection<PumpAlarmEvent>("pump_alarm_event")
|
||||
.InsertManyAsync(initialEvents);
|
||||
|
||||
var count = await _repo.Collection.CountDocumentsAsync(_ => true);
|
||||
Assert.That(count, Is.EqualTo(3));
|
||||
}
|
||||
new()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = DeviceA,
|
||||
PatientId = PatientId,
|
||||
AlarmType = PumpEnum.AlarmType.Attention,
|
||||
Time = Now.AddSeconds(-1)
|
||||
},
|
||||
new()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = DeviceA,
|
||||
PatientId = PatientId,
|
||||
AlarmType = PumpEnum.AlarmType.Occlusion,
|
||||
Time = Now.AddSeconds(-3)
|
||||
},
|
||||
new()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = DeviceB,
|
||||
PatientId = PatientId,
|
||||
AlarmType = PumpEnum.AlarmType.Occlusion,
|
||||
Time = Now.AddSeconds(-2)
|
||||
}
|
||||
};
|
||||
|
||||
await IntegrationDb.Database
|
||||
.GetCollection<PumpAlarmEvent>("pump_alarm_event")
|
||||
.InsertManyAsync(initialEvents);
|
||||
|
||||
var count = await _repo.Collection.CountDocumentsAsync(_ => true);
|
||||
Assert.That(count, Is.EqualTo(3));
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// INSERT
|
||||
// -------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that InsertAsync correctly persists a <see cref="PumpAlarmEvent"/> to the repository by inserting an event and confirming it can be retrieved by its identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task InsertAsync_Works()
|
||||
{
|
||||
var evt = new PumpAlarmEvent
|
||||
public async Task InsertAsync_Works()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-C",
|
||||
PatientId = PatientId,
|
||||
AlarmType = PumpEnum.AlarmType.Occlusion,
|
||||
Time = Now
|
||||
};
|
||||
|
||||
await _repo.InsertAsync(evt);
|
||||
|
||||
var found = await _repo.Collection.FindAsync(x => x.Id == evt.Id);
|
||||
Assert.That(found.FirstOrDefault(), Is.Not.Null);
|
||||
}
|
||||
var evt = new PumpAlarmEvent
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-C",
|
||||
PatientId = PatientId,
|
||||
AlarmType = PumpEnum.AlarmType.Occlusion,
|
||||
Time = Now
|
||||
};
|
||||
|
||||
await _repo.InsertAsync(evt);
|
||||
|
||||
var found = await _repo.Collection.FindAsync(x => x.Id == evt.Id);
|
||||
Assert.That(found.FirstOrDefault(), Is.Not.Null);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// FIND BY DEVICE ID
|
||||
// -------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that <c>FindByDeviceIdAsync</c> returns a non-empty collection of records for the specified device, ordered by time so that the most recent entry appears first.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByDeviceIdAsync_ReturnsOrdered()
|
||||
{
|
||||
var result = await _repo.FindByDeviceIdAsync(DeviceA);
|
||||
|
||||
var list = result.ToList();
|
||||
|
||||
using (Assert.EnterMultipleScope())
|
||||
public async Task FindByDeviceIdAsync_ReturnsOrdered()
|
||||
{
|
||||
Assert.That(list, Is.Not.Empty);
|
||||
Assert.That(list.First().Time, Is.GreaterThanOrEqualTo(list.Last().Time));
|
||||
var result = await _repo.FindByDeviceIdAsync(DeviceA);
|
||||
|
||||
var list = result.ToList();
|
||||
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(list, Is.Not.Empty);
|
||||
Assert.That(list.First().Time, Is.GreaterThanOrEqualTo(list.Last().Time));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>FindByDeviceIdAsync</c> returns only pump alarm events whose timestamps fall within the specified date range.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByDeviceIdAsync_WithDateRange_Works()
|
||||
{
|
||||
var from = Now.AddSeconds(-2);
|
||||
var to = Now;
|
||||
|
||||
var result = await _repo.FindByDeviceIdAsync(DeviceA, from, to);
|
||||
|
||||
using (Assert.EnterMultipleScope())
|
||||
public async Task FindByDeviceIdAsync_WithDateRange_Works()
|
||||
{
|
||||
var pumpAlarmEvents = result.ToList();
|
||||
Assert.That(pumpAlarmEvents, Is.Not.Empty);
|
||||
Assert.That(pumpAlarmEvents.All(x => x.Time >= from && x.Time <= to), Is.True);
|
||||
var from = Now.AddSeconds(-2);
|
||||
var to = Now;
|
||||
|
||||
var result = await _repo.FindByDeviceIdAsync(DeviceA, from, to);
|
||||
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
var pumpAlarmEvents = result.ToList();
|
||||
Assert.That(pumpAlarmEvents, Is.Not.Empty);
|
||||
Assert.That(pumpAlarmEvents.All(x => x.Time >= from && x.Time <= to), Is.True);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>FindByDeviceIdAsync</c> returns at most the specified number of results when a limit is provided.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByDeviceIdAsync_WithLimit_Works()
|
||||
{
|
||||
var result = await _repo.FindByDeviceIdAsync(DeviceA, limit: 1);
|
||||
|
||||
var list = result.ToList();
|
||||
Assert.That(list, Has.Count.EqualTo(1));
|
||||
}
|
||||
public async Task FindByDeviceIdAsync_WithLimit_Works()
|
||||
{
|
||||
var result = await _repo.FindByDeviceIdAsync(DeviceA, limit: 1);
|
||||
|
||||
var list = result.ToList();
|
||||
Assert.That(list, Has.Count.EqualTo(1));
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// FIND LAST BY DEVICE
|
||||
@@ -162,234 +180,270 @@ public class PumpAlarmEventRepositoryTest
|
||||
// -------------------------------------------------------------------
|
||||
// DELETE BY PATIENT ID
|
||||
// -------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that DeleteByPatientId correctly removes all alarm events associated with a given patient.
|
||||
/// Inserts a sample <c>PumpAlarmEvent</c> for a specific patient, deletes it by patient ID, and asserts that no matching events remain in the collection.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task DeleteByPatientId_Works()
|
||||
{
|
||||
var patient2 = ObjectId.GenerateNewId();
|
||||
|
||||
var evt = new PumpAlarmEvent
|
||||
public async Task DeleteByPatientId_Works()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-X",
|
||||
PatientId = patient2,
|
||||
AlarmType = PumpEnum.AlarmType.Occlusion,
|
||||
Time = Now
|
||||
};
|
||||
|
||||
await _repo.InsertAsync(evt);
|
||||
|
||||
await _repo.DeleteByPatientId(patient2);
|
||||
|
||||
var found = await _repo.Collection.FindAsync(x => x.PatientId == patient2);
|
||||
Assert.That(await found.AnyAsync(), Is.False);
|
||||
}
|
||||
var patient2 = ObjectId.GenerateNewId();
|
||||
|
||||
var evt = new PumpAlarmEvent
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-X",
|
||||
PatientId = patient2,
|
||||
AlarmType = PumpEnum.AlarmType.Occlusion,
|
||||
Time = Now
|
||||
};
|
||||
|
||||
await _repo.InsertAsync(evt);
|
||||
|
||||
await _repo.DeleteByPatientId(patient2);
|
||||
|
||||
var found = await _repo.Collection.FindAsync(x => x.PatientId == patient2);
|
||||
Assert.That(await found.AnyAsync(), Is.False);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// UPDATE MANY (CAMBIO DE PATIENTID O SIMILAR)
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>UpdateManyObjectIdByFiledNameAsync</c> correctly updates documents matching the specified field name and old ObjectId value, replacing it with the new ObjectId, and that the changes are persisted and queryable.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task UpdateManyObjectIdByFiledNameAsync_Works()
|
||||
{
|
||||
var oldId = ObjectId.GenerateNewId();
|
||||
var newId = ObjectId.GenerateNewId();
|
||||
|
||||
var evt = new PumpAlarmEvent
|
||||
public async Task UpdateManyObjectIdByFiledNameAsync_Works()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-U",
|
||||
PatientId = oldId,
|
||||
AlarmType = PumpEnum.AlarmType.Attention,
|
||||
Time = Now
|
||||
};
|
||||
|
||||
await _repo.InsertAsync(evt);
|
||||
|
||||
var updated = await _repo.UpdateManyObjectIdByFiledNameAsync("PatientId", newId, oldId);
|
||||
|
||||
Assert.That(updated, Is.EqualTo(1));
|
||||
|
||||
var found = await _repo.Collection.FindAsync(x => x.PatientId == newId);
|
||||
Assert.That(await found.AnyAsync(), Is.True);
|
||||
}
|
||||
var oldId = ObjectId.GenerateNewId();
|
||||
var newId = ObjectId.GenerateNewId();
|
||||
|
||||
[Test]
|
||||
public async Task FindByDeviceIdAsync_ReturnsEmpty_WhenOutOfRange()
|
||||
{
|
||||
var from = Now.AddYears(-2);
|
||||
var to = Now.AddYears(-2).AddDays(1);
|
||||
|
||||
var result = await _repo.FindByDeviceIdAsync("Device-A", from, to);
|
||||
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
var evt = new PumpAlarmEvent
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-U",
|
||||
PatientId = oldId,
|
||||
AlarmType = PumpEnum.AlarmType.Attention,
|
||||
Time = Now
|
||||
};
|
||||
|
||||
[Test]
|
||||
public async Task FindByDeviceIdAsync_RespectsLimitAndOrder()
|
||||
{
|
||||
// Semilla adicional para asegurar > 1
|
||||
var events = new[]
|
||||
{
|
||||
new PumpAlarmEvent { Id = ObjectId.GenerateNewId(), DeviceId = DeviceA, PatientId = PatientId, AlarmType = PumpEnum.AlarmType.AirInLine, Time = Now.AddMilliseconds(-10) },
|
||||
new PumpAlarmEvent { Id = ObjectId.GenerateNewId(), DeviceId = DeviceA, PatientId = PatientId, AlarmType = PumpEnum.AlarmType.Occlusion, Time = Now.AddMilliseconds(-5) }
|
||||
};
|
||||
await _repo.Collection.InsertManyAsync(events);
|
||||
|
||||
var result = await _repo.FindByDeviceIdAsync(DeviceA, limit: 1);
|
||||
var list = result.ToList();
|
||||
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(list, Has.Count.EqualTo(1));
|
||||
var last = await _repo.FindLastByDeviceIdAsync(DeviceA);
|
||||
Assert.That(list[0].Id, Is.EqualTo(last!.Id));
|
||||
await _repo.InsertAsync(evt);
|
||||
|
||||
var updated = await _repo.UpdateManyObjectIdByFiledNameAsync("PatientId", newId, oldId);
|
||||
|
||||
Assert.That(updated, Is.EqualTo(1));
|
||||
|
||||
var found = await _repo.Collection.FindAsync(x => x.PatientId == newId);
|
||||
Assert.That(await found.AnyAsync(), Is.True);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>FindByDeviceIdAsync</c> returns an empty result when the queried date range falls outside of the available data window.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task InsertAsync_AllowsNullOptionalFields()
|
||||
{
|
||||
var evt = new PumpAlarmEvent
|
||||
public async Task FindByDeviceIdAsync_ReturnsEmpty_WhenOutOfRange()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-Nulls",
|
||||
PatientId = null, // opcional
|
||||
AlarmType = null, // opcional
|
||||
Time = Now
|
||||
};
|
||||
|
||||
await _repo.InsertAsync(evt);
|
||||
|
||||
var found = await _repo.Collection.FindAsync(x => x.Id == evt.Id);
|
||||
Assert.That(found.FirstOrDefault(), Is.Not.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task DeleteByPatientId_DeletesMany_AndIsIdempotent()
|
||||
{
|
||||
var pid = ObjectId.GenerateNewId();
|
||||
|
||||
var docs = Enumerable.Range(0, 3).Select(i => new PumpAlarmEvent
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-Del",
|
||||
PatientId = pid,
|
||||
AlarmType = PumpEnum.AlarmType.Attention,
|
||||
Time = Now.AddSeconds(-i)
|
||||
});
|
||||
|
||||
await _repo.Collection.InsertManyAsync(docs);
|
||||
|
||||
// Primera vez: borra 3
|
||||
await _repo.DeleteByPatientId(pid);
|
||||
var left = await _repo.Collection.FindAsync(x => x.PatientId == pid);
|
||||
Assert.That(left.ToList(), Is.Empty);
|
||||
|
||||
Func<Task> act = async () => await _repo.DeleteByPatientId(pid);
|
||||
Assert.That(act, Throws.Nothing);
|
||||
}
|
||||
|
||||
var from = Now.AddYears(-2);
|
||||
var to = Now.AddYears(-2).AddDays(1);
|
||||
|
||||
[Test]
|
||||
public async Task UpdateManyObjectIdByFiledNameAsync_UpdatesMultiple()
|
||||
{
|
||||
var oldId = ObjectId.GenerateNewId();
|
||||
var newId = ObjectId.GenerateNewId();
|
||||
|
||||
var events = Enumerable.Range(0, 4).Select(i => new PumpAlarmEvent
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-U",
|
||||
PatientId = oldId,
|
||||
AlarmType = PumpEnum.AlarmType.AirInLine,
|
||||
Time = Now.AddMilliseconds(-i)
|
||||
});
|
||||
|
||||
await _repo.Collection.InsertManyAsync(events);
|
||||
|
||||
var modified = await _repo.UpdateManyObjectIdByFiledNameAsync("PatientId", newId, oldId);
|
||||
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(modified, Is.EqualTo(4));
|
||||
var foundNew = await _repo.Collection.FindAsync(x => x.PatientId == newId);
|
||||
Assert.That(foundNew.ToList(), Has.Count.EqualTo(4));
|
||||
var result = await _repo.FindByDeviceIdAsync("Device-A", from, to);
|
||||
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
}
|
||||
[Test]
|
||||
public async Task FindByDeviceIdAsync_InclusiveRange_BoundsRespected()
|
||||
{
|
||||
var start = Now.AddMinutes(-30);
|
||||
var end = Now.AddMinutes(-29);
|
||||
|
||||
var exactEvt = new PumpAlarmEvent
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-Range",
|
||||
PatientId = PatientId,
|
||||
AlarmType = PumpEnum.AlarmType.Attention,
|
||||
Time = end // exactamente igual al to
|
||||
};
|
||||
|
||||
await _repo.InsertAsync(exactEvt);
|
||||
|
||||
var result = await _repo.FindByDeviceIdAsync("Device-Range", from: start, to: end);
|
||||
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
var pumpAlarmEvents = result as PumpAlarmEvent[] ?? result.ToArray();
|
||||
Assert.That(pumpAlarmEvents, Is.Not.Empty);
|
||||
Assert.That(pumpAlarmEvents.All(r => r.Time >= start && r.Time <= end), Is.True);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>FindByDeviceIdAsync</c> correctly applies the requested limit and orders results so that the most recent alarm event for the given device is returned first.
|
||||
/// Seeds multiple events for the target device, requests a single record, and asserts that the returned entry matches the latest event retrieved by <c>FindLastByDeviceIdAsync</c>.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindLastByDeviceIdAsync_TracksNewest()
|
||||
{
|
||||
const string dev = "Device-LastCheck";
|
||||
|
||||
var e1 = new PumpAlarmEvent { Id = ObjectId.GenerateNewId(), DeviceId = dev, PatientId = PatientId, AlarmType = PumpEnum.AlarmType.AirInLine, Time = Now.AddSeconds(-10) };
|
||||
var e2 = new PumpAlarmEvent { Id = ObjectId.GenerateNewId(), DeviceId = dev, PatientId = PatientId, AlarmType = PumpEnum.AlarmType.Occlusion, Time = Now.AddSeconds(-5) };
|
||||
|
||||
await _repo.Collection.InsertManyAsync([e1, e2]);
|
||||
|
||||
var last1 = await _repo.FindLastByDeviceIdAsync(dev);
|
||||
Assert.That(last1!.Id, Is.EqualTo(e2.Id));
|
||||
|
||||
var e3 = new PumpAlarmEvent { Id = ObjectId.GenerateNewId(), DeviceId = dev, PatientId = PatientId, AlarmType = PumpEnum.AlarmType.Attention, Time = Now };
|
||||
await _repo.InsertAsync(e3);
|
||||
|
||||
var last2 = await _repo.FindLastByDeviceIdAsync(dev);
|
||||
Assert.That(last2!.Id, Is.EqualTo(e3.Id));
|
||||
}
|
||||
public async Task FindByDeviceIdAsync_RespectsLimitAndOrder()
|
||||
{
|
||||
// Semilla adicional para asegurar > 1
|
||||
var events = new[]
|
||||
{
|
||||
new PumpAlarmEvent { Id = ObjectId.GenerateNewId(), DeviceId = DeviceA, PatientId = PatientId, AlarmType = PumpEnum.AlarmType.AirInLine, Time = Now.AddMilliseconds(-10) },
|
||||
new PumpAlarmEvent { Id = ObjectId.GenerateNewId(), DeviceId = DeviceA, PatientId = PatientId, AlarmType = PumpEnum.AlarmType.Occlusion, Time = Now.AddMilliseconds(-5) }
|
||||
};
|
||||
await _repo.Collection.InsertManyAsync(events);
|
||||
|
||||
[Test]
|
||||
public async Task FindByDeviceIdAsync_MultipleOverlappingRanges()
|
||||
{
|
||||
const string dev = "Device-Timeline";
|
||||
|
||||
var batch = new[]
|
||||
{
|
||||
new PumpAlarmEvent { Id = ObjectId.GenerateNewId(), DeviceId = dev, PatientId = PatientId, AlarmType = PumpEnum.AlarmType.AirInLine, Time = Now.AddMinutes(-20) },
|
||||
new PumpAlarmEvent { Id = ObjectId.GenerateNewId(), DeviceId = dev, PatientId = PatientId, AlarmType = PumpEnum.AlarmType.Occlusion, Time = Now.AddMinutes(-10) },
|
||||
new PumpAlarmEvent { Id = ObjectId.GenerateNewId(), DeviceId = dev, PatientId = PatientId, AlarmType = PumpEnum.AlarmType.Attention, Time = Now.AddMinutes(-5) }
|
||||
};
|
||||
|
||||
await _repo.Collection.InsertManyAsync(batch);
|
||||
|
||||
var r1 = await _repo.FindByDeviceIdAsync(dev, from: Now.AddMinutes(-30), to: Now.AddMinutes(-15));
|
||||
var r2 = await _repo.FindByDeviceIdAsync(dev, from: Now.AddMinutes(-12), to: Now.AddMinutes(-8));
|
||||
var r3 = await _repo.FindByDeviceIdAsync(dev, from: Now.AddMinutes(-6), to: Now);
|
||||
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
var r1List = r1.ToList();
|
||||
Assert.That(r1List, Has.Count.EqualTo(1)); // -20
|
||||
var r2List = r2.ToList();
|
||||
Assert.That(r2List, Has.Count.EqualTo(1)); // -10
|
||||
var r3List = r3.ToList();
|
||||
Assert.That(r3List, Has.Count.EqualTo(1)); // -5
|
||||
var result = await _repo.FindByDeviceIdAsync(DeviceA, limit: 1);
|
||||
var list = result.ToList();
|
||||
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(list, Has.Count.EqualTo(1));
|
||||
var last = await _repo.FindLastByDeviceIdAsync(DeviceA);
|
||||
Assert.That(list[0].Id, Is.EqualTo(last!.Id));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that InsertAsync successfully persists a <see cref="PumpAlarmEvent"/> when its optional fields (<c>PatientId</c> and <c>AlarmType</c>) are <c>null</c>, and that the record can be retrieved afterwards.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task InsertAsync_AllowsNullOptionalFields()
|
||||
{
|
||||
var evt = new PumpAlarmEvent
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-Nulls",
|
||||
PatientId = null, // opcional
|
||||
AlarmType = null, // opcional
|
||||
Time = Now
|
||||
};
|
||||
|
||||
await _repo.InsertAsync(evt);
|
||||
|
||||
var found = await _repo.Collection.FindAsync(x => x.Id == evt.Id);
|
||||
Assert.That(found.FirstOrDefault(), Is.Not.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>DeleteByPatientId</c> removes all alarm events associated with the given patient and can be invoked repeatedly without throwing once the records no longer exist.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task DeleteByPatientId_DeletesMany_AndIsIdempotent()
|
||||
{
|
||||
var pid = ObjectId.GenerateNewId();
|
||||
|
||||
var docs = Enumerable.Range(0, 3).Select(i => new PumpAlarmEvent
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-Del",
|
||||
PatientId = pid,
|
||||
AlarmType = PumpEnum.AlarmType.Attention,
|
||||
Time = Now.AddSeconds(-i)
|
||||
});
|
||||
|
||||
await _repo.Collection.InsertManyAsync(docs);
|
||||
|
||||
// Primera vez: borra 3
|
||||
await _repo.DeleteByPatientId(pid);
|
||||
var left = await _repo.Collection.FindAsync(x => x.PatientId == pid);
|
||||
Assert.That(left.ToList(), Is.Empty);
|
||||
|
||||
Func<Task> act = async () => await _repo.DeleteByPatientId(pid);
|
||||
Assert.That(act, Throws.Nothing);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>UpdateManyObjectIdByFiledNameAsync</c> updates the <c>PatientId</c> field from an old <see cref="ObjectId"/> to a new one across all matching documents, returning the modified count and persisting the new identifier in the collection.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task UpdateManyObjectIdByFiledNameAsync_UpdatesMultiple()
|
||||
{
|
||||
var oldId = ObjectId.GenerateNewId();
|
||||
var newId = ObjectId.GenerateNewId();
|
||||
|
||||
var events = Enumerable.Range(0, 4).Select(i => new PumpAlarmEvent
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-U",
|
||||
PatientId = oldId,
|
||||
AlarmType = PumpEnum.AlarmType.AirInLine,
|
||||
Time = Now.AddMilliseconds(-i)
|
||||
});
|
||||
|
||||
await _repo.Collection.InsertManyAsync(events);
|
||||
|
||||
var modified = await _repo.UpdateManyObjectIdByFiledNameAsync("PatientId", newId, oldId);
|
||||
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(modified, Is.EqualTo(4));
|
||||
var foundNew = await _repo.Collection.FindAsync(x => x.PatientId == newId);
|
||||
Assert.That(foundNew.ToList(), Has.Count.EqualTo(4));
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Verifies that <c>FindByDeviceIdAsync</c> treats the <c>from</c> and <c>to</c> time bounds as inclusive,
|
||||
/// ensuring events whose timestamp matches the upper bound exactly are returned and that all returned
|
||||
/// events fall within the supplied range.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByDeviceIdAsync_InclusiveRange_BoundsRespected()
|
||||
{
|
||||
var start = Now.AddMinutes(-30);
|
||||
var end = Now.AddMinutes(-29);
|
||||
|
||||
var exactEvt = new PumpAlarmEvent
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-Range",
|
||||
PatientId = PatientId,
|
||||
AlarmType = PumpEnum.AlarmType.Attention,
|
||||
Time = end // exactamente igual al to
|
||||
};
|
||||
|
||||
await _repo.InsertAsync(exactEvt);
|
||||
|
||||
var result = await _repo.FindByDeviceIdAsync("Device-Range", from: start, to: end);
|
||||
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
var pumpAlarmEvents = result as PumpAlarmEvent[] ?? result.ToArray();
|
||||
Assert.That(pumpAlarmEvents, Is.Not.Empty);
|
||||
Assert.That(pumpAlarmEvents.All(r => r.Time >= start && r.Time <= end), Is.True);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that FindLastByDeviceIdAsync returns the most recent alarm event for a given device and tracks newly inserted events as the latest entry.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindLastByDeviceIdAsync_TracksNewest()
|
||||
{
|
||||
const string dev = "Device-LastCheck";
|
||||
|
||||
var e1 = new PumpAlarmEvent { Id = ObjectId.GenerateNewId(), DeviceId = dev, PatientId = PatientId, AlarmType = PumpEnum.AlarmType.AirInLine, Time = Now.AddSeconds(-10) };
|
||||
var e2 = new PumpAlarmEvent { Id = ObjectId.GenerateNewId(), DeviceId = dev, PatientId = PatientId, AlarmType = PumpEnum.AlarmType.Occlusion, Time = Now.AddSeconds(-5) };
|
||||
|
||||
await _repo.Collection.InsertManyAsync([e1, e2]);
|
||||
|
||||
var last1 = await _repo.FindLastByDeviceIdAsync(dev);
|
||||
Assert.That(last1!.Id, Is.EqualTo(e2.Id));
|
||||
|
||||
var e3 = new PumpAlarmEvent { Id = ObjectId.GenerateNewId(), DeviceId = dev, PatientId = PatientId, AlarmType = PumpEnum.AlarmType.Attention, Time = Now };
|
||||
await _repo.InsertAsync(e3);
|
||||
|
||||
var last2 = await _repo.FindLastByDeviceIdAsync(dev);
|
||||
Assert.That(last2!.Id, Is.EqualTo(e3.Id));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>FindByDeviceIdAsync</c> correctly filters pump alarm events by device identifier
|
||||
/// and time range when multiple queries are issued against overlapping windows, ensuring each
|
||||
/// range returns only the event that falls within its boundaries.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByDeviceIdAsync_MultipleOverlappingRanges()
|
||||
{
|
||||
const string dev = "Device-Timeline";
|
||||
|
||||
var batch = new[]
|
||||
{
|
||||
new PumpAlarmEvent { Id = ObjectId.GenerateNewId(), DeviceId = dev, PatientId = PatientId, AlarmType = PumpEnum.AlarmType.AirInLine, Time = Now.AddMinutes(-20) },
|
||||
new PumpAlarmEvent { Id = ObjectId.GenerateNewId(), DeviceId = dev, PatientId = PatientId, AlarmType = PumpEnum.AlarmType.Occlusion, Time = Now.AddMinutes(-10) },
|
||||
new PumpAlarmEvent { Id = ObjectId.GenerateNewId(), DeviceId = dev, PatientId = PatientId, AlarmType = PumpEnum.AlarmType.Attention, Time = Now.AddMinutes(-5) }
|
||||
};
|
||||
|
||||
await _repo.Collection.InsertManyAsync(batch);
|
||||
|
||||
var r1 = await _repo.FindByDeviceIdAsync(dev, from: Now.AddMinutes(-30), to: Now.AddMinutes(-15));
|
||||
var r2 = await _repo.FindByDeviceIdAsync(dev, from: Now.AddMinutes(-12), to: Now.AddMinutes(-8));
|
||||
var r3 = await _repo.FindByDeviceIdAsync(dev, from: Now.AddMinutes(-6), to: Now);
|
||||
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
var r1List = r1.ToList();
|
||||
Assert.That(r1List, Has.Count.EqualTo(1)); // -20
|
||||
var r2List = r2.ToList();
|
||||
Assert.That(r2List, Has.Count.EqualTo(1)); // -10
|
||||
var r3List = r3.ToList();
|
||||
Assert.That(r3List, Has.Count.EqualTo(1)); // -5
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,108 +23,123 @@ public class PumpAlarmStateRepositoryTest
|
||||
// -------------------------------------------------------------------
|
||||
// INIT: preparar colección, índices y datos iniciales
|
||||
// -------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// One-time setup that prepares the integration test environment for <see cref="PumpAlarmStateRepository"/>.
|
||||
/// Configures the API settings, drops and recreates the "pump_alarm_state" collection, instantiates the repository with its indexes, and seeds three initial alarm state records across two devices, verifying the seeded count.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
_apiSettings = Options.Create(new ApiSettings
|
||||
public async Task Init()
|
||||
{
|
||||
PumpAlarmState = "pump_alarm_state"
|
||||
});
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("pump_alarm_state");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("pump_alarm_state");
|
||||
|
||||
_repo = new PumpAlarmStateRepository(
|
||||
_apiSettings,
|
||||
IntegrationDb.Database
|
||||
);
|
||||
|
||||
await _repo.CreateIndexes();
|
||||
|
||||
// datos iniciales
|
||||
var initial = new List<PumpAlarmState>
|
||||
{
|
||||
new()
|
||||
_apiSettings = Options.Create(new ApiSettings
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = DeviceA,
|
||||
PatientId = PatientId,
|
||||
AlarmType = PumpEnum.AlarmType.Attention,
|
||||
AlarmCodeMdc = "AC001",
|
||||
LastUpdated = Now.AddSeconds(-3)
|
||||
},
|
||||
new()
|
||||
PumpAlarmState = "pump_alarm_state"
|
||||
});
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("pump_alarm_state");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("pump_alarm_state");
|
||||
|
||||
_repo = new PumpAlarmStateRepository(
|
||||
_apiSettings,
|
||||
IntegrationDb.Database
|
||||
);
|
||||
|
||||
await _repo.CreateIndexes();
|
||||
|
||||
// datos iniciales
|
||||
var initial = new List<PumpAlarmState>
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = DeviceA,
|
||||
PatientId = PatientId,
|
||||
AlarmType = PumpEnum.AlarmType.Occlusion,
|
||||
AlarmCodeMdc = "AC002",
|
||||
LastUpdated = Now.AddSeconds(-1)
|
||||
},
|
||||
new()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = DeviceB,
|
||||
PatientId = PatientId,
|
||||
AlarmType = PumpEnum.AlarmType.Occlusion,
|
||||
AlarmCodeMdc = "AC003",
|
||||
LastUpdated = Now.AddSeconds(-2)
|
||||
}
|
||||
};
|
||||
|
||||
await _repo.Collection.InsertManyAsync(initial);
|
||||
|
||||
var count = await _repo.Collection.CountDocumentsAsync(_ => true);
|
||||
Assert.That(count, Is.EqualTo(3));
|
||||
}
|
||||
new()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = DeviceA,
|
||||
PatientId = PatientId,
|
||||
AlarmType = PumpEnum.AlarmType.Attention,
|
||||
AlarmCodeMdc = "AC001",
|
||||
LastUpdated = Now.AddSeconds(-3)
|
||||
},
|
||||
new()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = DeviceA,
|
||||
PatientId = PatientId,
|
||||
AlarmType = PumpEnum.AlarmType.Occlusion,
|
||||
AlarmCodeMdc = "AC002",
|
||||
LastUpdated = Now.AddSeconds(-1)
|
||||
},
|
||||
new()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = DeviceB,
|
||||
PatientId = PatientId,
|
||||
AlarmType = PumpEnum.AlarmType.Occlusion,
|
||||
AlarmCodeMdc = "AC003",
|
||||
LastUpdated = Now.AddSeconds(-2)
|
||||
}
|
||||
};
|
||||
|
||||
await _repo.Collection.InsertManyAsync(initial);
|
||||
|
||||
var count = await _repo.Collection.CountDocumentsAsync(_ => true);
|
||||
Assert.That(count, Is.EqualTo(3));
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// FIND ACTIVE
|
||||
// -------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that <c>FindActiveAsync</c> returns the correct active alarm matching the specified device identifier, alarm type, and alarm code.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindActiveAsync_ReturnsCorrectAlarm()
|
||||
{
|
||||
var alarm = await _repo.FindActiveAsync(DeviceA, PumpEnum.AlarmType.Occlusion, "AC002");
|
||||
|
||||
using (Assert.EnterMultipleScope())
|
||||
public async Task FindActiveAsync_ReturnsCorrectAlarm()
|
||||
{
|
||||
Assert.That(alarm, Is.Not.Null);
|
||||
Assert.That(alarm!.DeviceId, Is.EqualTo(DeviceA));
|
||||
Assert.That(alarm.AlarmType, Is.EqualTo(PumpEnum.AlarmType.Occlusion));
|
||||
Assert.That(alarm.AlarmCodeMdc, Is.EqualTo("AC002"));
|
||||
var alarm = await _repo.FindActiveAsync(DeviceA, PumpEnum.AlarmType.Occlusion, "AC002");
|
||||
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(alarm, Is.Not.Null);
|
||||
Assert.That(alarm!.DeviceId, Is.EqualTo(DeviceA));
|
||||
Assert.That(alarm.AlarmType, Is.EqualTo(PumpEnum.AlarmType.Occlusion));
|
||||
Assert.That(alarm.AlarmCodeMdc, Is.EqualTo("AC002"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>FindActiveAsync</c> returns <c>null</c> when no active alarm matching the specified device, alarm type, and identifier exists.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindActiveAsync_ReturnsNull_WhenNotFound()
|
||||
{
|
||||
var alarm = await _repo.FindActiveAsync(DeviceA, PumpEnum.AlarmType.Occlusion, "XXX");
|
||||
Assert.That(alarm, Is.Null);
|
||||
}
|
||||
public async Task FindActiveAsync_ReturnsNull_WhenNotFound()
|
||||
{
|
||||
var alarm = await _repo.FindActiveAsync(DeviceA, PumpEnum.AlarmType.Occlusion, "XXX");
|
||||
Assert.That(alarm, Is.Null);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// UPSERT ACTIVE
|
||||
// -------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that <c>UpsertActiveAsync</c> correctly inserts a new active pump alarm into the repository
|
||||
/// when no existing alarm with the same device, type, and code is found, and that the inserted alarm
|
||||
/// can subsequently be retrieved via <c>FindActiveAsync</c>.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task UpsertActiveAsync_InsertsNew()
|
||||
{
|
||||
var alarm = new PumpAlarmState
|
||||
public async Task UpsertActiveAsync_InsertsNew()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-C",
|
||||
AlarmType = PumpEnum.AlarmType.Attention,
|
||||
AlarmCodeMdc = "NEW",
|
||||
PatientId = PatientId,
|
||||
LastUpdated = Now
|
||||
};
|
||||
|
||||
await _repo.UpsertActiveAsync(alarm);
|
||||
|
||||
var found = await _repo.FindActiveAsync("Device-C", PumpEnum.AlarmType.Attention, "NEW");
|
||||
|
||||
Assert.That(found, Is.Not.Null);
|
||||
}
|
||||
var alarm = new PumpAlarmState
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-C",
|
||||
AlarmType = PumpEnum.AlarmType.Attention,
|
||||
AlarmCodeMdc = "NEW",
|
||||
PatientId = PatientId,
|
||||
LastUpdated = Now
|
||||
};
|
||||
|
||||
await _repo.UpsertActiveAsync(alarm);
|
||||
|
||||
var found = await _repo.FindActiveAsync("Device-C", PumpEnum.AlarmType.Attention, "NEW");
|
||||
|
||||
Assert.That(found, Is.Not.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task UpsertActiveAsync_UpdatesExisting()
|
||||
@@ -150,98 +165,113 @@ public class PumpAlarmStateRepositoryTest
|
||||
// -------------------------------------------------------------------
|
||||
// REMOVE ACTIVE ALARM
|
||||
// -------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that <c>RemoveAsync</c> correctly deletes an active alarm by device, alarm type, and alarm code, and that a subsequent lookup returns no result.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task RemoveAsync_Works()
|
||||
{
|
||||
var alarm = new PumpAlarmState
|
||||
public async Task RemoveAsync_Works()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-D",
|
||||
AlarmType = PumpEnum.AlarmType.Attention,
|
||||
AlarmCodeMdc = "D1",
|
||||
PatientId = PatientId,
|
||||
LastUpdated = Now
|
||||
};
|
||||
|
||||
await _repo.UpsertActiveAsync(alarm);
|
||||
|
||||
await _repo.RemoveAsync("Device-D", PumpEnum.AlarmType.Attention, "D1");
|
||||
|
||||
var found = await _repo.FindActiveAsync("Device-D", PumpEnum.AlarmType.Attention, "D1");
|
||||
Assert.That(found, Is.Null);
|
||||
}
|
||||
var alarm = new PumpAlarmState
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-D",
|
||||
AlarmType = PumpEnum.AlarmType.Attention,
|
||||
AlarmCodeMdc = "D1",
|
||||
PatientId = PatientId,
|
||||
LastUpdated = Now
|
||||
};
|
||||
|
||||
await _repo.UpsertActiveAsync(alarm);
|
||||
|
||||
await _repo.RemoveAsync("Device-D", PumpEnum.AlarmType.Attention, "D1");
|
||||
|
||||
var found = await _repo.FindActiveAsync("Device-D", PumpEnum.AlarmType.Attention, "D1");
|
||||
Assert.That(found, Is.Null);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// DELETE BY PATIENT ID
|
||||
// -------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that the repository's <c>DeleteByPatientId</c> method successfully removes a previously upserted
|
||||
/// <see cref="PumpAlarmState"/> for the specified patient, ensuring no matching records remain in the collection.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task DeleteByPatientId_Works()
|
||||
{
|
||||
var pid = ObjectId.GenerateNewId();
|
||||
|
||||
var alarm = new PumpAlarmState
|
||||
public async Task DeleteByPatientId_Works()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-E",
|
||||
AlarmType = PumpEnum.AlarmType.Occlusion,
|
||||
AlarmCodeMdc = "DDD",
|
||||
PatientId = pid,
|
||||
LastUpdated = Now
|
||||
};
|
||||
|
||||
await _repo.UpsertActiveAsync(alarm);
|
||||
|
||||
await _repo.DeleteByPatientId(pid);
|
||||
|
||||
var list = await _repo.Collection.FindAsync(x => x.PatientId == pid);
|
||||
Assert.That(await list.AnyAsync(), Is.False);
|
||||
}
|
||||
var pid = ObjectId.GenerateNewId();
|
||||
|
||||
var alarm = new PumpAlarmState
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-E",
|
||||
AlarmType = PumpEnum.AlarmType.Occlusion,
|
||||
AlarmCodeMdc = "DDD",
|
||||
PatientId = pid,
|
||||
LastUpdated = Now
|
||||
};
|
||||
|
||||
await _repo.UpsertActiveAsync(alarm);
|
||||
|
||||
await _repo.DeleteByPatientId(pid);
|
||||
|
||||
var list = await _repo.Collection.FindAsync(x => x.PatientId == pid);
|
||||
Assert.That(await list.AnyAsync(), Is.False);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// FIND ALL ACTIVE BY DEVICE
|
||||
// -------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that <c>FindAllActiveByDeviceAsync</c> returns only active pump alarm states that belong to the specified device.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindAllActiveByDeviceAsync_ReturnsCorrect()
|
||||
{
|
||||
var result = await _repo.FindAllActiveByDeviceAsync(DeviceA);
|
||||
|
||||
var pumpAlarmStates = result.ToList();
|
||||
Assert.That(pumpAlarmStates, Is.Not.Empty);
|
||||
Assert.That(pumpAlarmStates.All(x => x.DeviceId == DeviceA), Is.True);
|
||||
}
|
||||
public async Task FindAllActiveByDeviceAsync_ReturnsCorrect()
|
||||
{
|
||||
var result = await _repo.FindAllActiveByDeviceAsync(DeviceA);
|
||||
|
||||
var pumpAlarmStates = result.ToList();
|
||||
Assert.That(pumpAlarmStates, Is.Not.Empty);
|
||||
Assert.That(pumpAlarmStates.All(x => x.DeviceId == DeviceA), Is.True);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// UPDATE MANY BY FIELD
|
||||
// -------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that <c>UpdateManyObjectIdByFieldNameAsync</c> successfully updates the <c>PatientId</c> field
|
||||
/// from the old ObjectId to a new ObjectId for matching documents, returning the expected count of
|
||||
/// updated records and making the document retrievable by the new ObjectId.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task UpdateManyObjectIdByFieldNameAsync_Works()
|
||||
{
|
||||
var oldId = ObjectId.GenerateNewId();
|
||||
var newId = ObjectId.GenerateNewId();
|
||||
|
||||
// Insert one alarm to update
|
||||
var alarm = new PumpAlarmState
|
||||
public async Task UpdateManyObjectIdByFieldNameAsync_Works()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-F",
|
||||
AlarmType = PumpEnum.AlarmType.Occlusion,
|
||||
AlarmCodeMdc = "FFF",
|
||||
PatientId = oldId,
|
||||
LastUpdated = Now
|
||||
};
|
||||
|
||||
await _repo.UpsertActiveAsync(alarm);
|
||||
|
||||
var updated = await _repo.UpdateManyObjectIdByFieldNameAsync("PatientId", newId, oldId);
|
||||
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(updated, Is.EqualTo(1));
|
||||
|
||||
var found = await _repo.Collection.FindAsync(x => x.PatientId == newId);
|
||||
Assert.That(await found.AnyAsync(), Is.True);
|
||||
var oldId = ObjectId.GenerateNewId();
|
||||
var newId = ObjectId.GenerateNewId();
|
||||
|
||||
// Insert one alarm to update
|
||||
var alarm = new PumpAlarmState
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-F",
|
||||
AlarmType = PumpEnum.AlarmType.Occlusion,
|
||||
AlarmCodeMdc = "FFF",
|
||||
PatientId = oldId,
|
||||
LastUpdated = Now
|
||||
};
|
||||
|
||||
await _repo.UpsertActiveAsync(alarm);
|
||||
|
||||
var updated = await _repo.UpdateManyObjectIdByFieldNameAsync("PatientId", newId, oldId);
|
||||
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(updated, Is.EqualTo(1));
|
||||
|
||||
var found = await _repo.Collection.FindAsync(x => x.PatientId == newId);
|
||||
Assert.That(await found.AnyAsync(), Is.True);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task UpsertActiveAsync_NoDuplicateOnRepeatedCalls()
|
||||
@@ -264,60 +294,66 @@ public class PumpAlarmStateRepositoryTest
|
||||
Assert.That(list, Has.Count.EqualTo(1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that UpsertActiveAsync correctly inserts a PumpAlarmState record when the AlarmCodeMdc is null, and that the record can be retrieved via FindActiveAsync using a null alarm code.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task UpsertActiveAsync_InsertsWhenAlarmCodeIsNull()
|
||||
{
|
||||
var alarm = new PumpAlarmState
|
||||
public async Task UpsertActiveAsync_InsertsWhenAlarmCodeIsNull()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-NullCode",
|
||||
AlarmType = PumpEnum.AlarmType.Occlusion,
|
||||
AlarmCodeMdc = null,
|
||||
PatientId = PatientId,
|
||||
LastUpdated = Now
|
||||
};
|
||||
|
||||
await _repo.UpsertActiveAsync(alarm);
|
||||
|
||||
var found = await _repo.FindActiveAsync("Device-NullCode", PumpEnum.AlarmType.Occlusion, null);
|
||||
|
||||
Assert.That(found, Is.Not.Null);
|
||||
Assert.That(found!.AlarmCodeMdc, Is.Null);
|
||||
}
|
||||
var alarm = new PumpAlarmState
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-NullCode",
|
||||
AlarmType = PumpEnum.AlarmType.Occlusion,
|
||||
AlarmCodeMdc = null,
|
||||
PatientId = PatientId,
|
||||
LastUpdated = Now
|
||||
};
|
||||
|
||||
await _repo.UpsertActiveAsync(alarm);
|
||||
|
||||
var found = await _repo.FindActiveAsync("Device-NullCode", PumpEnum.AlarmType.Occlusion, null);
|
||||
|
||||
Assert.That(found, Is.Not.Null);
|
||||
Assert.That(found!.AlarmCodeMdc, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>RemoveAsync</c> removes every active alarm matching the specified device identifier and alarm type, not just a single record.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task RemoveAsync_RemovesAllMatching()
|
||||
{
|
||||
var alarms = new[]
|
||||
public async Task RemoveAsync_RemovesAllMatching()
|
||||
{
|
||||
new PumpAlarmState
|
||||
var alarms = new[]
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-Multi",
|
||||
AlarmType = PumpEnum.AlarmType.AirInLine,
|
||||
AlarmCodeMdc = "XX1",
|
||||
PatientId = PatientId,
|
||||
LastUpdated = Now
|
||||
},
|
||||
new PumpAlarmState
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-Multi",
|
||||
AlarmType = PumpEnum.AlarmType.AirInLine,
|
||||
AlarmCodeMdc = "XX2",
|
||||
PatientId = PatientId,
|
||||
LastUpdated = Now
|
||||
}
|
||||
};
|
||||
|
||||
foreach (var a in alarms)
|
||||
await _repo.UpsertActiveAsync(a);
|
||||
|
||||
await _repo.RemoveAsync("Device-Multi", PumpEnum.AlarmType.AirInLine);
|
||||
|
||||
var remaining = await _repo.FindAllActiveByDeviceAsync("Device-Multi");
|
||||
|
||||
Assert.That(remaining, Is.Empty);
|
||||
}
|
||||
new PumpAlarmState
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-Multi",
|
||||
AlarmType = PumpEnum.AlarmType.AirInLine,
|
||||
AlarmCodeMdc = "XX1",
|
||||
PatientId = PatientId,
|
||||
LastUpdated = Now
|
||||
},
|
||||
new PumpAlarmState
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = "Device-Multi",
|
||||
AlarmType = PumpEnum.AlarmType.AirInLine,
|
||||
AlarmCodeMdc = "XX2",
|
||||
PatientId = PatientId,
|
||||
LastUpdated = Now
|
||||
}
|
||||
};
|
||||
|
||||
foreach (var a in alarms)
|
||||
await _repo.UpsertActiveAsync(a);
|
||||
|
||||
await _repo.RemoveAsync("Device-Multi", PumpEnum.AlarmType.AirInLine);
|
||||
|
||||
var remaining = await _repo.FindAllActiveByDeviceAsync("Device-Multi");
|
||||
|
||||
Assert.That(remaining, Is.Empty);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -175,19 +175,22 @@ public class PumpArchiveRepositoryTest
|
||||
private static readonly DateTime Now = DateTime.Now;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the <c>DeleteBeforeDate</c> repository method removes all records with a date earlier than the specified cutoff, retaining only records dated on or after that cutoff.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task DeleteBeforeDate()
|
||||
{
|
||||
var result = await _repository.Collection.FindAsync(_ => true);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.ToList(), Has.Count.GreaterThan(1));
|
||||
|
||||
await _repository.DeleteBeforeDate(Now.AddDays(-1));
|
||||
|
||||
var resultDelete = await _repository.Collection.FindAsync(_ => true);
|
||||
|
||||
Assert.That(resultDelete, Is.Not.Null);
|
||||
Assert.That(resultDelete.ToList(), Has.Count.EqualTo(1));
|
||||
}
|
||||
public async Task DeleteBeforeDate()
|
||||
{
|
||||
var result = await _repository.Collection.FindAsync(_ => true);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.ToList(), Has.Count.GreaterThan(1));
|
||||
|
||||
await _repository.DeleteBeforeDate(Now.AddDays(-1));
|
||||
|
||||
var resultDelete = await _repository.Collection.FindAsync(_ => true);
|
||||
|
||||
Assert.That(resultDelete, Is.Not.Null);
|
||||
Assert.That(resultDelete.ToList(), Has.Count.EqualTo(1));
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,11 @@ public class PumpStateRepositoryTest
|
||||
// ============================================================
|
||||
// INIT
|
||||
// ============================================================
|
||||
/// <summary>
|
||||
/// One-time setup that prepares the integration test environment for the PumpStateRepository by recreating the
|
||||
/// "pump_states" MongoDB collection, building the repository indexes, and seeding two initial pump states (one
|
||||
/// actively infusing for a known patient/device and one not infusing) to verify the baseline document count.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
@@ -43,26 +48,26 @@ public class PumpStateRepositoryTest
|
||||
|
||||
// Insertar estados iniciales
|
||||
var initialStates = new List<PumpState>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = DeviceA,
|
||||
PatientId = PatientId,
|
||||
LastUpdated = Now,
|
||||
IsInfusing = true,
|
||||
Status = PumpEnum.Status.Infusing,
|
||||
PumpMode = PumpEnum.Mode.Infusing
|
||||
},
|
||||
new()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = DeviceB,
|
||||
LastUpdated = Now.AddSeconds(-10),
|
||||
IsInfusing = false,
|
||||
Status = PumpEnum.Status.NotInfusing
|
||||
}
|
||||
};
|
||||
new()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = DeviceA,
|
||||
PatientId = PatientId,
|
||||
LastUpdated = Now,
|
||||
IsInfusing = true,
|
||||
Status = PumpEnum.Status.Infusing,
|
||||
PumpMode = PumpEnum.Mode.Infusing
|
||||
},
|
||||
new()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
DeviceId = DeviceB,
|
||||
LastUpdated = Now.AddSeconds(-10),
|
||||
IsInfusing = false,
|
||||
Status = PumpEnum.Status.NotInfusing
|
||||
}
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.GetCollection<PumpState>("pump_states")
|
||||
.InsertManyAsync(initialStates);
|
||||
@@ -74,6 +79,9 @@ public class PumpStateRepositoryTest
|
||||
// ============================================================
|
||||
// FIND BY DEVICE ID
|
||||
// ============================================================
|
||||
/// <summary>
|
||||
/// Verifies that FindByDeviceIdAsync retrieves the correct infusion state for a given device, returning a non-null result that matches the requested device identifier and reflects the expected infusion status.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByDeviceIdAsync_ReturnsCorrectState()
|
||||
{
|
||||
@@ -90,6 +98,9 @@ public class PumpStateRepositoryTest
|
||||
// ============================================================
|
||||
// UPSERT (INSERT + UPDATE)
|
||||
// ============================================================
|
||||
/// <summary>
|
||||
/// Verifies that <c>UpsertAsync</c> inserts a new <see cref="PumpState"/> record when no existing entry is found for the specified <c>DeviceId</c>, and that the persisted state retains the provided property values.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task UpsertAsync_InsertsNewWhenNotExists()
|
||||
{
|
||||
@@ -108,6 +119,11 @@ public class PumpStateRepositoryTest
|
||||
Assert.That(found!.IsInfusing, Is.False);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>UpsertAsync</c> correctly updates an existing pump state in the repository, ensuring
|
||||
/// the updated <see cref="PumpState"/> is persisted and retrievable with the modified <c>IsInfusing</c>,
|
||||
/// <c>Status</c>, and <c>LastUpdated</c> values.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task UpsertAsync_UpdatesExistingState()
|
||||
{
|
||||
@@ -130,7 +146,7 @@ public class PumpStateRepositoryTest
|
||||
Assert.That(found!.IsInfusing, Is.False);
|
||||
Assert.That(found.Status, Is.EqualTo(PumpEnum.Status.NotInfusing));
|
||||
Assert.That(
|
||||
found.LastUpdated,
|
||||
found.LastUpdated,
|
||||
Is.EqualTo(updated.LastUpdated).Within(TimeSpan.FromMilliseconds(1))
|
||||
);
|
||||
}
|
||||
@@ -139,6 +155,9 @@ public class PumpStateRepositoryTest
|
||||
// ============================================================
|
||||
// GET ALL
|
||||
// ============================================================
|
||||
/// <summary>
|
||||
/// Verifies that <c>GetAllAsync</c> returns a non-null collection of pump states containing at least two entries, including those associated with the seeded devices A and B.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetAllAsync_ReturnsAllStates()
|
||||
{
|
||||
@@ -161,6 +180,9 @@ public class PumpStateRepositoryTest
|
||||
// ============================================================
|
||||
// UNIQUE INDEX: UPSERT OVERWRITES (NO DUPLICADOS)
|
||||
// ============================================================
|
||||
/// <summary>
|
||||
/// Verifies that UpsertAsync updates an existing entity instead of inserting a duplicate, ensuring the total record count remains unchanged when upserting a <see cref="PumpState"/> for an already-known device identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task UpsertAsync_DoesNotCreateDuplicates()
|
||||
{
|
||||
|
||||
@@ -12,35 +12,38 @@ namespace adas_core.Test.Repositories;
|
||||
[Category("Integration")]
|
||||
public class RecordingAlertArchiveRepositoryTest
|
||||
{
|
||||
/// <summary>
|
||||
/// One-time test setup that prepares the archive collection for recording-alert integration tests by clearing it, creating a fresh instance of <see cref="RecordingAlertArchiveRepository"/>, and seeding it with two patient recording alerts (one matching the current patient with the current timestamp and one for a different patient dated ten days earlier), verifying that both records are persisted.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var recordingAlert1 = new PatientRecordingAlert
|
||||
public async Task Init()
|
||||
{
|
||||
PatientId = PatientId,
|
||||
IsRecording = true,
|
||||
Time = Now
|
||||
};
|
||||
|
||||
var recordingAlert2 = new PatientRecordingAlert
|
||||
{
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
IsRecording = true,
|
||||
Time = Now.AddDays(-10)
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("archive_patients_recordingalerts");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("archive_patients_recordingalerts");
|
||||
|
||||
_repository = new RecordingAlertArchiveRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(recordingAlert1);
|
||||
await _repository.InsertOneAsync(recordingAlert2);
|
||||
|
||||
Assert.That(await _repository.Collection.CountDocumentsAsync(_ => true), Is.EqualTo(2));
|
||||
}
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var recordingAlert1 = new PatientRecordingAlert
|
||||
{
|
||||
PatientId = PatientId,
|
||||
IsRecording = true,
|
||||
Time = Now
|
||||
};
|
||||
|
||||
var recordingAlert2 = new PatientRecordingAlert
|
||||
{
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
IsRecording = true,
|
||||
Time = Now.AddDays(-10)
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("archive_patients_recordingalerts");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("archive_patients_recordingalerts");
|
||||
|
||||
_repository = new RecordingAlertArchiveRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(recordingAlert1);
|
||||
await _repository.InsertOneAsync(recordingAlert2);
|
||||
|
||||
Assert.That(await _repository.Collection.CountDocumentsAsync(_ => true), Is.EqualTo(2));
|
||||
}
|
||||
|
||||
private RecordingAlertArchiveRepository _repository;
|
||||
|
||||
@@ -55,19 +58,23 @@ public class RecordingAlertArchiveRepositoryTest
|
||||
private static readonly ObjectId PatientId = ObjectId.GenerateNewId();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's <c>DeleteBeforeDate</c> operation removes all documents dated before the specified cutoff date, leaving only documents on or after that date.
|
||||
/// Expects more than one document in the collection initially and exactly one remaining after deletion.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task DeleteBeforeDate()
|
||||
{
|
||||
var result = await _repository.Collection.FindAsync(_ => true);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.ToList(), Has.Count.GreaterThan(1));
|
||||
|
||||
await _repository.DeleteBeforeDate(Now.AddDays(-1));
|
||||
|
||||
var resultDelete = await _repository.Collection.FindAsync(_ => true);
|
||||
|
||||
Assert.That(resultDelete, Is.Not.Null);
|
||||
Assert.That(resultDelete.ToList(), Has.Count.EqualTo(1));
|
||||
}
|
||||
public async Task DeleteBeforeDate()
|
||||
{
|
||||
var result = await _repository.Collection.FindAsync(_ => true);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.ToList(), Has.Count.GreaterThan(1));
|
||||
|
||||
await _repository.DeleteBeforeDate(Now.AddDays(-1));
|
||||
|
||||
var resultDelete = await _repository.Collection.FindAsync(_ => true);
|
||||
|
||||
Assert.That(resultDelete, Is.Not.Null);
|
||||
Assert.That(resultDelete.ToList(), Has.Count.EqualTo(1));
|
||||
}
|
||||
}
|
||||
@@ -12,35 +12,39 @@ namespace adas_core.Test.Repositories;
|
||||
[Category("Integration")]
|
||||
public class RecordingAlertRepositoryTest
|
||||
{
|
||||
/// <summary>
|
||||
/// One-time test setup that initializes the recording alert repository with two sample patient recording alerts
|
||||
/// and ensures the underlying collection contains exactly two documents for integration test scenarios.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var recordingAlert1 = new PatientRecordingAlert
|
||||
public async Task Init()
|
||||
{
|
||||
PatientId = PatientId,
|
||||
IsRecording = true,
|
||||
Time = Now
|
||||
};
|
||||
|
||||
var recordingAlert2 = new PatientRecordingAlert
|
||||
{
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
IsRecording = true,
|
||||
Time = Now.AddDays(-10)
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("archive_patients_recordingalerts");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("archive_patients_recordingalerts");
|
||||
|
||||
_repository = new RecordingAlertRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(recordingAlert1);
|
||||
await _repository.InsertOneAsync(recordingAlert2);
|
||||
|
||||
Assert.That(await _repository.Collection.CountDocumentsAsync(_ => true), Is.EqualTo(2));
|
||||
}
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var recordingAlert1 = new PatientRecordingAlert
|
||||
{
|
||||
PatientId = PatientId,
|
||||
IsRecording = true,
|
||||
Time = Now
|
||||
};
|
||||
|
||||
var recordingAlert2 = new PatientRecordingAlert
|
||||
{
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
IsRecording = true,
|
||||
Time = Now.AddDays(-10)
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("archive_patients_recordingalerts");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("archive_patients_recordingalerts");
|
||||
|
||||
_repository = new RecordingAlertRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(recordingAlert1);
|
||||
await _repository.InsertOneAsync(recordingAlert2);
|
||||
|
||||
Assert.That(await _repository.Collection.CountDocumentsAsync(_ => true), Is.EqualTo(2));
|
||||
}
|
||||
|
||||
private RecordingAlertRepository _repository;
|
||||
|
||||
@@ -55,227 +59,251 @@ public class RecordingAlertRepositoryTest
|
||||
private static readonly ObjectId PatientId = ObjectId.GenerateNewId();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's DeleteAsync method successfully removes a PatientRecordingAlert document, confirming the record exists prior to deletion and is no longer retrievable afterwards.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task DeleteAsync()
|
||||
{
|
||||
var recordingAlert = new PatientRecordingAlert
|
||||
public async Task DeleteAsync()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
IsRecording = true,
|
||||
Time = Now
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(recordingAlert);
|
||||
|
||||
var result = await _repository.Collection.FindAsync(p => p.Id == recordingAlert.Id);
|
||||
|
||||
Assert.That(result.FirstOrDefault(), Is.Not.Null);
|
||||
|
||||
await _repository.DeleteAsync(recordingAlert.Id);
|
||||
|
||||
var resultDelete = await _repository.Collection.FindAsync(p => p.Id == recordingAlert.Id);
|
||||
|
||||
Assert.That(resultDelete.FirstOrDefault(), Is.Null);
|
||||
}
|
||||
var recordingAlert = new PatientRecordingAlert
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
IsRecording = true,
|
||||
Time = Now
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(recordingAlert);
|
||||
|
||||
var result = await _repository.Collection.FindAsync(p => p.Id == recordingAlert.Id);
|
||||
|
||||
Assert.That(result.FirstOrDefault(), Is.Not.Null);
|
||||
|
||||
await _repository.DeleteAsync(recordingAlert.Id);
|
||||
|
||||
var resultDelete = await _repository.Collection.FindAsync(p => p.Id == recordingAlert.Id);
|
||||
|
||||
Assert.That(resultDelete.FirstOrDefault(), Is.Null);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Tests that the <c>DeleteOlderDaysAsync</c> repository method removes patient recording alerts that exceed the specified age threshold and match the given recording name, while preserving alerts within the threshold.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task DeleteOlderDaysAsync()
|
||||
{
|
||||
var recordingAlert = new PatientRecordingAlert
|
||||
public async Task DeleteOlderDaysAsync()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
IsRecording = true,
|
||||
Time = Now,
|
||||
Name = "recordingName1"
|
||||
};
|
||||
|
||||
var recordingAlertOld = new PatientRecordingAlert
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = recordingAlert.PatientId,
|
||||
IsRecording = true,
|
||||
Time = Now.AddDays(-5),
|
||||
Name = "recordingName1"
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(recordingAlert);
|
||||
await _repository.InsertOneAsync(recordingAlertOld);
|
||||
|
||||
var result = await _repository.Collection.FindAsync(p => p.PatientId == recordingAlert.PatientId);
|
||||
|
||||
Assert.That(result.ToList(), Has.Count.EqualTo(2));
|
||||
|
||||
await _repository.DeleteOlderDaysAsync("recordingName1", 2);
|
||||
|
||||
var resultDelete = await _repository.Collection.FindAsync(p => p.PatientId == recordingAlert.PatientId);
|
||||
|
||||
Assert.That(resultDelete.ToList(), Has.Count.EqualTo(1));
|
||||
|
||||
await _repository.Collection.DeleteManyAsync(d => d.PatientId == recordingAlert.PatientId);
|
||||
|
||||
var resultClear = await _repository.Collection.FindAsync(p => p.PatientId == recordingAlert.PatientId);
|
||||
|
||||
Assert.That(resultClear.ToList(), Has.Count.EqualTo(0));
|
||||
}
|
||||
var recordingAlert = new PatientRecordingAlert
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
IsRecording = true,
|
||||
Time = Now,
|
||||
Name = "recordingName1"
|
||||
};
|
||||
|
||||
var recordingAlertOld = new PatientRecordingAlert
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = recordingAlert.PatientId,
|
||||
IsRecording = true,
|
||||
Time = Now.AddDays(-5),
|
||||
Name = "recordingName1"
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(recordingAlert);
|
||||
await _repository.InsertOneAsync(recordingAlertOld);
|
||||
|
||||
var result = await _repository.Collection.FindAsync(p => p.PatientId == recordingAlert.PatientId);
|
||||
|
||||
Assert.That(result.ToList(), Has.Count.EqualTo(2));
|
||||
|
||||
await _repository.DeleteOlderDaysAsync("recordingName1", 2);
|
||||
|
||||
var resultDelete = await _repository.Collection.FindAsync(p => p.PatientId == recordingAlert.PatientId);
|
||||
|
||||
Assert.That(resultDelete.ToList(), Has.Count.EqualTo(1));
|
||||
|
||||
await _repository.Collection.DeleteManyAsync(d => d.PatientId == recordingAlert.PatientId);
|
||||
|
||||
var resultClear = await _repository.Collection.FindAsync(p => p.PatientId == recordingAlert.PatientId);
|
||||
|
||||
Assert.That(resultClear.ToList(), Has.Count.EqualTo(0));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>DeleteOlderNumberAsync</c> removes older records with the specified name, keeping only the most recent ones according to the provided count.
|
||||
/// Inserts two <see cref="PatientRecordingAlert"/> entries sharing the same name but different timestamps, asserts both exist, performs the deletion, and confirms that only one record remains.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task DeleteOlderNumberAsync()
|
||||
{
|
||||
var recordingAlert = new PatientRecordingAlert
|
||||
public async Task DeleteOlderNumberAsync()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
IsRecording = true,
|
||||
Time = Now,
|
||||
Name = "recordingName1"
|
||||
};
|
||||
|
||||
var recordingAlertOld = new PatientRecordingAlert
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = recordingAlert.PatientId,
|
||||
IsRecording = true,
|
||||
Time = Now.AddDays(-5),
|
||||
Name = "recordingName1"
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(recordingAlert);
|
||||
await _repository.InsertOneAsync(recordingAlertOld);
|
||||
|
||||
var result = await _repository.Collection.FindAsync(p => p.Name == "recordingName1");
|
||||
|
||||
Assert.That(result.ToList(), Has.Count.EqualTo(2));
|
||||
|
||||
await _repository.DeleteOlderNumberAsync("recordingName1", 1);
|
||||
|
||||
var resultDelete = await _repository.Collection.FindAsync(p => p.Name == "recordingName1");
|
||||
|
||||
Assert.That(resultDelete.ToList(), Has.Count.EqualTo(1));
|
||||
}
|
||||
var recordingAlert = new PatientRecordingAlert
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
IsRecording = true,
|
||||
Time = Now,
|
||||
Name = "recordingName1"
|
||||
};
|
||||
|
||||
var recordingAlertOld = new PatientRecordingAlert
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = recordingAlert.PatientId,
|
||||
IsRecording = true,
|
||||
Time = Now.AddDays(-5),
|
||||
Name = "recordingName1"
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(recordingAlert);
|
||||
await _repository.InsertOneAsync(recordingAlertOld);
|
||||
|
||||
var result = await _repository.Collection.FindAsync(p => p.Name == "recordingName1");
|
||||
|
||||
Assert.That(result.ToList(), Has.Count.EqualTo(2));
|
||||
|
||||
await _repository.DeleteOlderNumberAsync("recordingName1", 1);
|
||||
|
||||
var resultDelete = await _repository.Collection.FindAsync(p => p.Name == "recordingName1");
|
||||
|
||||
Assert.That(resultDelete.ToList(), Has.Count.EqualTo(1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>DeleteByPatientId</c> removes a patient's recording alert from the repository, ensuring the alert cannot be retrieved after deletion.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task DeleteByPatientId()
|
||||
{
|
||||
var recordingAlert = new PatientRecordingAlert
|
||||
public async Task DeleteByPatientId()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
IsRecording = true,
|
||||
Time = Now
|
||||
};
|
||||
|
||||
var recordingAlertOld = new PatientRecordingAlert
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = recordingAlert.PatientId,
|
||||
IsRecording = true,
|
||||
Time = Now.AddDays(-5)
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(recordingAlert);
|
||||
await _repository.InsertOneAsync(recordingAlertOld);
|
||||
|
||||
var result = await _repository.Collection.FindAsync(p => p.PatientId == recordingAlert.PatientId);
|
||||
|
||||
Assert.That(result.FirstOrDefault(), Is.Not.Null);
|
||||
|
||||
await _repository.DeleteByPatientId(recordingAlert.PatientId);
|
||||
|
||||
var resultDelete = await _repository.Collection.FindAsync(p => p.PatientId == recordingAlert.PatientId);
|
||||
|
||||
Assert.That(resultDelete.FirstOrDefault(), Is.Null);
|
||||
}
|
||||
var recordingAlert = new PatientRecordingAlert
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
IsRecording = true,
|
||||
Time = Now
|
||||
};
|
||||
|
||||
var recordingAlertOld = new PatientRecordingAlert
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = recordingAlert.PatientId,
|
||||
IsRecording = true,
|
||||
Time = Now.AddDays(-5)
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(recordingAlert);
|
||||
await _repository.InsertOneAsync(recordingAlertOld);
|
||||
|
||||
var result = await _repository.Collection.FindAsync(p => p.PatientId == recordingAlert.PatientId);
|
||||
|
||||
Assert.That(result.FirstOrDefault(), Is.Not.Null);
|
||||
|
||||
await _repository.DeleteByPatientId(recordingAlert.PatientId);
|
||||
|
||||
var resultDelete = await _repository.Collection.FindAsync(p => p.PatientId == recordingAlert.PatientId);
|
||||
|
||||
Assert.That(resultDelete.FirstOrDefault(), Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository returns a non-null result when searching for records by patient identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByPatientIdAsync()
|
||||
{
|
||||
var result = await _repository.FindByPatientIdAsync(PatientId);
|
||||
|
||||
Assert.That(result.FirstOrDefault(), Is.Not.Null);
|
||||
}
|
||||
public async Task FindByPatientIdAsync()
|
||||
{
|
||||
var result = await _repository.FindByPatientIdAsync(PatientId);
|
||||
|
||||
Assert.That(result.FirstOrDefault(), Is.Not.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>FindLastObservations</c> returns only the most recent recording alert
|
||||
/// for a given patient and recording name, filtering out older entries based on the
|
||||
/// specified count limit, and that the returned observation matches the expected time.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindLastObservations()
|
||||
{
|
||||
var recordingAlert = new PatientRecordingAlert
|
||||
public async Task FindLastObservations()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
IsRecording = true,
|
||||
Time = Now,
|
||||
Name = "recordingName1"
|
||||
};
|
||||
|
||||
var recordingAlertOld = new PatientRecordingAlert
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = recordingAlert.PatientId,
|
||||
IsRecording = true,
|
||||
Time = Now.AddDays(-5),
|
||||
Name = "recordingName1"
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(recordingAlert);
|
||||
await _repository.InsertOneAsync(recordingAlertOld);
|
||||
|
||||
var result = await _repository.Collection.FindAsync(_ => true);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.ToList(), Has.Count.GreaterThan(2));
|
||||
|
||||
var resultFind = await _repository.FindLastObservations(recordingAlert.PatientId, "recordingName1", 1);
|
||||
|
||||
Assert.That(resultFind, Is.Not.Null);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(resultFind.ToList(), Has.Count.EqualTo(1));
|
||||
Assert.That(resultFind.FirstOrDefault()?.Time.Day, Is.EqualTo(Now.Day));
|
||||
Assert.That(resultFind.FirstOrDefault()?.Time.Month, Is.EqualTo(Now.Month));
|
||||
Assert.That(resultFind.FirstOrDefault()?.Time.Year, Is.EqualTo(Now.Year));
|
||||
};
|
||||
await _repository.DeleteByPatientId(recordingAlert.PatientId);
|
||||
|
||||
var resultDelete = await _repository.Collection.FindAsync(p => p.PatientId == recordingAlert.PatientId);
|
||||
|
||||
Assert.That(resultDelete.FirstOrDefault(), Is.Null);
|
||||
}
|
||||
var recordingAlert = new PatientRecordingAlert
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
IsRecording = true,
|
||||
Time = Now,
|
||||
Name = "recordingName1"
|
||||
};
|
||||
|
||||
var recordingAlertOld = new PatientRecordingAlert
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = recordingAlert.PatientId,
|
||||
IsRecording = true,
|
||||
Time = Now.AddDays(-5),
|
||||
Name = "recordingName1"
|
||||
};
|
||||
|
||||
await _repository.InsertOneAsync(recordingAlert);
|
||||
await _repository.InsertOneAsync(recordingAlertOld);
|
||||
|
||||
var result = await _repository.Collection.FindAsync(_ => true);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.ToList(), Has.Count.GreaterThan(2));
|
||||
|
||||
var resultFind = await _repository.FindLastObservations(recordingAlert.PatientId, "recordingName1", 1);
|
||||
|
||||
Assert.That(resultFind, Is.Not.Null);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(resultFind.ToList(), Has.Count.EqualTo(1));
|
||||
Assert.That(resultFind.FirstOrDefault()?.Time.Day, Is.EqualTo(Now.Day));
|
||||
Assert.That(resultFind.FirstOrDefault()?.Time.Month, Is.EqualTo(Now.Month));
|
||||
Assert.That(resultFind.FirstOrDefault()?.Time.Year, Is.EqualTo(Now.Year));
|
||||
};
|
||||
await _repository.DeleteByPatientId(recordingAlert.PatientId);
|
||||
|
||||
var resultDelete = await _repository.Collection.FindAsync(p => p.PatientId == recordingAlert.PatientId);
|
||||
|
||||
Assert.That(resultDelete.FirstOrDefault(), Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the repository's ability to update the <c>patientid</c> ObjectId field across records, verifying that after the update the original patient identifier no longer returns any alerts while the new patient identifier does, and that deletion by patient ID subsequently removes the record.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task UpdateManyObjectId()
|
||||
{
|
||||
var recordingAlert = new PatientRecordingAlert
|
||||
public async Task UpdateManyObjectId()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
IsRecording = true,
|
||||
Time = Now
|
||||
};
|
||||
|
||||
var newPatientId = ObjectId.GenerateNewId();
|
||||
|
||||
await _repository.InsertOneAsync(recordingAlert);
|
||||
|
||||
var result = await _repository.FindByPatientIdAsync(recordingAlert.PatientId);
|
||||
|
||||
Assert.That(result.FirstOrDefault(), Is.Not.Null);
|
||||
|
||||
await _repository.UpdateManyObjectId("patientid", newPatientId, recordingAlert.PatientId);
|
||||
|
||||
var resultOldId = await _repository.FindByPatientIdAsync(recordingAlert.PatientId);
|
||||
|
||||
Assert.That(resultOldId.FirstOrDefault(), Is.Null);
|
||||
|
||||
var resultNewId = await _repository.FindByPatientIdAsync(newPatientId);
|
||||
|
||||
Assert.That(resultNewId.FirstOrDefault(), Is.Not.Null);
|
||||
|
||||
await _repository.DeleteByPatientId(newPatientId);
|
||||
|
||||
var resultDelete = await _repository.FindByPatientIdAsync(newPatientId);
|
||||
|
||||
Assert.That(resultDelete.FirstOrDefault(), Is.Null);
|
||||
}
|
||||
var recordingAlert = new PatientRecordingAlert
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
IsRecording = true,
|
||||
Time = Now
|
||||
};
|
||||
|
||||
var newPatientId = ObjectId.GenerateNewId();
|
||||
|
||||
await _repository.InsertOneAsync(recordingAlert);
|
||||
|
||||
var result = await _repository.FindByPatientIdAsync(recordingAlert.PatientId);
|
||||
|
||||
Assert.That(result.FirstOrDefault(), Is.Not.Null);
|
||||
|
||||
await _repository.UpdateManyObjectId("patientid", newPatientId, recordingAlert.PatientId);
|
||||
|
||||
var resultOldId = await _repository.FindByPatientIdAsync(recordingAlert.PatientId);
|
||||
|
||||
Assert.That(resultOldId.FirstOrDefault(), Is.Null);
|
||||
|
||||
var resultNewId = await _repository.FindByPatientIdAsync(newPatientId);
|
||||
|
||||
Assert.That(resultNewId.FirstOrDefault(), Is.Not.Null);
|
||||
|
||||
await _repository.DeleteByPatientId(newPatientId);
|
||||
|
||||
var resultDelete = await _repository.FindByPatientIdAsync(newPatientId);
|
||||
|
||||
Assert.That(resultDelete.FirstOrDefault(), Is.Null);
|
||||
}
|
||||
}
|
||||
@@ -11,24 +11,27 @@ namespace adas_core.Test.Repositories;
|
||||
[Category("Integration")]
|
||||
public class ServiceConfigRepositoryTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Performs one-time initialization for integration tests by creating a <see cref="ServiceConfig"/> entry in the test database and preparing the repository used by the test fixture.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var serviceConfig = new ServiceConfig
|
||||
public async Task Init()
|
||||
{
|
||||
Id = _id,
|
||||
StrId = Id.ToString()
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("service_config");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("service_config");
|
||||
|
||||
_repository = new ServiceConfigRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(serviceConfig);
|
||||
}
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var serviceConfig = new ServiceConfig
|
||||
{
|
||||
Id = _id,
|
||||
StrId = Id.ToString()
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("service_config");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("service_config");
|
||||
|
||||
_repository = new ServiceConfigRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(serviceConfig);
|
||||
}
|
||||
|
||||
private ServiceConfigRepository _repository;
|
||||
|
||||
@@ -43,21 +46,29 @@ public class ServiceConfigRepositoryTest
|
||||
private static readonly ObjectId Id = ObjectId.GenerateNewId();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="_repository"/>.FindById returns a non-null entity when queried by its string identifier,
|
||||
/// and that the returned entity's <c>StrId</c> matches the supplied id.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindById_Find_string()
|
||||
{
|
||||
var result = await _repository.FindById(Id.ToString());
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result!.StrId, Is.EqualTo(Id.ToString()));
|
||||
}
|
||||
public async Task FindById_Find_string()
|
||||
{
|
||||
var result = await _repository.FindById(Id.ToString());
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result!.StrId, Is.EqualTo(Id.ToString()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's FindById method successfully retrieves an object by its identifier,
|
||||
/// returning a non-null result whose Id matches the requested identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindById_Find_ObjectId()
|
||||
{
|
||||
var result = await _repository.FindById(_id);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result!.Id, Is.EqualTo(_id));
|
||||
}
|
||||
public async Task FindById_Find_ObjectId()
|
||||
{
|
||||
var result = await _repository.FindById(_id);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result!.Id, Is.EqualTo(_id));
|
||||
}
|
||||
}
|
||||
@@ -13,47 +13,50 @@ namespace adas_core.Test.Repositories;
|
||||
[Category("Integration")]
|
||||
public class TreatmentArchiveRepositoryTest
|
||||
{
|
||||
/// <summary>
|
||||
/// One-time setup method that prepares the integration test environment for the treatment archive repository by creating and inserting two sample patient treatments (one new and one discontinued) into a freshly created archive collection.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var treatment1 = new PatientTreatment
|
||||
public async Task Init()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = PatientId,
|
||||
OrderControl = OrderControlType.Nw,
|
||||
PlacerOrder = new Entity { EntityIdentifier = "3690", NamespaceId = "CareVue" },
|
||||
FillerOrder = new Entity { EntityIdentifier = "3690", NamespaceId = "CareVue" },
|
||||
OrderStatus = "A",
|
||||
OrderTime = DateTime.Now,
|
||||
Notes = [],
|
||||
Routes = []
|
||||
};
|
||||
|
||||
var treatment2 = new PatientTreatment
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = PatientId,
|
||||
OrderControl = OrderControlType.Dc,
|
||||
PlacerOrder = new Entity { EntityIdentifier = "3690", NamespaceId = "CareVue" },
|
||||
FillerOrder = new Entity { EntityIdentifier = "3690", NamespaceId = "CareVue" },
|
||||
OrderStatus = "A",
|
||||
OrderTime = DateTime.Now.AddDays(-5),
|
||||
Notes = [],
|
||||
Routes = []
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("archive_patients_treatments");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("archive_patients_treatments");
|
||||
|
||||
_repository = new TreatmentArchiveRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(treatment1);
|
||||
await _repository.InsertOneAsync(treatment2);
|
||||
|
||||
Assert.That(_repository.Collection.FindAsync(_ => true).Result.ToList(), Has.Count.EqualTo(2));
|
||||
}
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var treatment1 = new PatientTreatment
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = PatientId,
|
||||
OrderControl = OrderControlType.Nw,
|
||||
PlacerOrder = new Entity { EntityIdentifier = "3690", NamespaceId = "CareVue" },
|
||||
FillerOrder = new Entity { EntityIdentifier = "3690", NamespaceId = "CareVue" },
|
||||
OrderStatus = "A",
|
||||
OrderTime = DateTime.Now,
|
||||
Notes = [],
|
||||
Routes = []
|
||||
};
|
||||
|
||||
var treatment2 = new PatientTreatment
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = PatientId,
|
||||
OrderControl = OrderControlType.Dc,
|
||||
PlacerOrder = new Entity { EntityIdentifier = "3690", NamespaceId = "CareVue" },
|
||||
FillerOrder = new Entity { EntityIdentifier = "3690", NamespaceId = "CareVue" },
|
||||
OrderStatus = "A",
|
||||
OrderTime = DateTime.Now.AddDays(-5),
|
||||
Notes = [],
|
||||
Routes = []
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("archive_patients_treatments");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("archive_patients_treatments");
|
||||
|
||||
_repository = new TreatmentArchiveRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(treatment1);
|
||||
await _repository.InsertOneAsync(treatment2);
|
||||
|
||||
Assert.That(_repository.Collection.FindAsync(_ => true).Result.ToList(), Has.Count.EqualTo(2));
|
||||
}
|
||||
|
||||
private TreatmentArchiveRepository _repository;
|
||||
|
||||
@@ -68,28 +71,35 @@ public class TreatmentArchiveRepositoryTest
|
||||
private static readonly ObjectId PatientId = ObjectId.GenerateNewId();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Tests the <see cref="DeleteBeforeDate"/> repository method to ensure it correctly removes records older than the specified cutoff date,
|
||||
/// leaving only the most recent record. Verifies that when multiple patient records exist, deletion by date retains exactly one record.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task DeleteBeforeDate()
|
||||
{
|
||||
var result = await _repository.Collection.FindAsync(p => p.PatientId == PatientId);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.ToList(), Has.Count.GreaterThan(1));
|
||||
|
||||
await _repository.DeleteBeforeDate(Now.AddHours(-2));
|
||||
|
||||
var resultDelete = await _repository.Collection.FindAsync(p => p.PatientId == PatientId);
|
||||
|
||||
Assert.That(resultDelete, Is.Not.Null);
|
||||
Assert.That(resultDelete.ToList(), Has.Count.EqualTo(1));
|
||||
}
|
||||
public async Task DeleteBeforeDate()
|
||||
{
|
||||
var result = await _repository.Collection.FindAsync(p => p.PatientId == PatientId);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.ToList(), Has.Count.GreaterThan(1));
|
||||
|
||||
await _repository.DeleteBeforeDate(Now.AddHours(-2));
|
||||
|
||||
var resultDelete = await _repository.Collection.FindAsync(p => p.PatientId == PatientId);
|
||||
|
||||
Assert.That(resultDelete, Is.Not.Null);
|
||||
Assert.That(resultDelete.ToList(), Has.Count.EqualTo(1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository successfully retrieves a non-empty collection of records associated with the specified patient.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindAllFromPatient()
|
||||
{
|
||||
var result = await _repository.FindAllFromPatient(PatientId);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.ToList(), Has.Count.GreaterThan(0));
|
||||
}
|
||||
public async Task FindAllFromPatient()
|
||||
{
|
||||
var result = await _repository.FindAllFromPatient(PatientId);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.ToList(), Has.Count.GreaterThan(0));
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,9 @@ namespace adas_core.Test.Repositories;
|
||||
[Category("Integration")]
|
||||
public class TreatmentRepositoryTest
|
||||
{
|
||||
/// <summary>
|
||||
/// One-time test setup that resets the treatments collection, instantiates the repository, and seeds two patient treatments (one with OrderControlType.Nw and one with OrderControlType.Dc) to verify insert behavior.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
@@ -45,7 +48,7 @@ public class TreatmentRepositoryTest
|
||||
RequestedGiveCodesStatus =
|
||||
[
|
||||
new CodeStatus
|
||||
{ Code = new Code { CodingSystem = "CS", Identifier = "I", Text = "T" }, Status = "status" }
|
||||
{ Code = new Code { CodingSystem = "CS", Identifier = "I", Text = "T" }, Status = "status" }
|
||||
]
|
||||
};
|
||||
|
||||
@@ -75,6 +78,9 @@ public class TreatmentRepositoryTest
|
||||
private PatientTreatment _treatment2 = null!;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that GetByPatientId returns an empty result collection rather than null when no patient treatments are found for the supplied patient identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetByPatientId_Not_Find_Return_Null()
|
||||
{
|
||||
@@ -85,6 +91,10 @@ public class TreatmentRepositoryTest
|
||||
Assert.That(patientTreatments.ToList(), Is.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that the repository's <c>GetByPatientId</c> method returns the expected patient treatment records
|
||||
/// for the given patient, verifying that the result is not null and contains the expected number of entries.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetByPatientId_Find_Return_Null()
|
||||
{
|
||||
@@ -95,6 +105,10 @@ public class TreatmentRepositoryTest
|
||||
Assert.That(patientTreatments.ToList(), Has.Count.EqualTo(2));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="DeleteAsync"/> successfully removes a persisted patient treatment from the repository.
|
||||
/// The test inserts a treatment, confirms it exists, deletes it by id, and asserts it is no longer retrievable.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task DeleteAsync()
|
||||
{
|
||||
@@ -126,6 +140,9 @@ public class TreatmentRepositoryTest
|
||||
Assert.That(resultDelete.ToList(), Has.Count.EqualTo(0));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>FindByPatientIdAsync</c> returns a non-null list containing the expected number of treatments for the specified patient.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByPatientIdAsync_Find_Return_List_Traetments()
|
||||
{
|
||||
@@ -135,6 +152,9 @@ public class TreatmentRepositoryTest
|
||||
Assert.That(result.ToList(), Has.Count.EqualTo(2));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="DeleteByPatientId"/> removes the patient treatment associated with the given patient identifier, ensuring no records remain for that patient after deletion.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task DeleteByPatientId()
|
||||
{
|
||||
@@ -166,6 +186,9 @@ public class TreatmentRepositoryTest
|
||||
Assert.That(resultDelete.ToList(), Has.Count.EqualTo(0));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that _repository.FindBolusTreatments returns a non-null collection containing exactly one bolus treatment for the specified patient.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindBolusTreatments_Find_Return_Treatment()
|
||||
{
|
||||
@@ -175,6 +198,9 @@ public class TreatmentRepositoryTest
|
||||
Assert.That(result.ToList(), Has.Count.EqualTo(1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that FindByPatientIdAsync returns a non-null list containing the expected number of treatments for the specified patient.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByPatientId_Find_Return_List_Traetments()
|
||||
{
|
||||
|
||||
@@ -12,36 +12,39 @@ namespace adas_core.Test.Repositories;
|
||||
[Category("Integration")]
|
||||
public class UnitRepositoryTest
|
||||
{
|
||||
/// <summary>
|
||||
/// One-time setup method that prepares the integration test environment by configuring API settings, creating a fresh "units" collection in the database, and seeding it with two sample <see cref="Unit"/> records via the <see cref="UnitRepository"/>.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
// Set up your test environment, including database connection
|
||||
|
||||
// Mocking ApiSettings
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
// Creating sample unit data
|
||||
var unit1 = new Unit
|
||||
public async Task Init()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Name = "unit1"
|
||||
// Add other properties as needed
|
||||
};
|
||||
|
||||
var unit2 = new Unit
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Name = "unit2"
|
||||
// Add other properties as needed
|
||||
};
|
||||
|
||||
// Insert sample data into the database
|
||||
await IntegrationDb.Database.DropCollectionAsync("units");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("units");
|
||||
_repository = new UnitRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
await _repository.InsertOneUnit(unit1);
|
||||
await _repository.InsertOneUnit(unit2);
|
||||
}
|
||||
// Set up your test environment, including database connection
|
||||
|
||||
// Mocking ApiSettings
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
// Creating sample unit data
|
||||
var unit1 = new Unit
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Name = "unit1"
|
||||
// Add other properties as needed
|
||||
};
|
||||
|
||||
var unit2 = new Unit
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Name = "unit2"
|
||||
// Add other properties as needed
|
||||
};
|
||||
|
||||
// Insert sample data into the database
|
||||
await IntegrationDb.Database.DropCollectionAsync("units");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("units");
|
||||
_repository = new UnitRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
await _repository.InsertOneUnit(unit1);
|
||||
await _repository.InsertOneUnit(unit2);
|
||||
}
|
||||
|
||||
private UnitRepository _repository;
|
||||
|
||||
@@ -52,37 +55,40 @@ public class UnitRepositoryTest
|
||||
|
||||
private IOptions<ApiSettings> _optionsApiSettings;
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that inserting a valid <see cref="Unit"/> into the repository returns the unit and that the inserted unit can be successfully retrieved by its identifier, with key properties preserved.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task InsertOneUnit_ValidUnit_ReturnsUnit()
|
||||
{
|
||||
// Arrange
|
||||
var unit = new Unit
|
||||
public async Task InsertOneUnit_ValidUnit_ReturnsUnit()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Title = "Test Unit",
|
||||
Name = "Test Unit",
|
||||
LastUpdate = DateTime.UtcNow,
|
||||
PointOfCareIds = [ObjectId.GenerateNewId()],
|
||||
Status = StatusEnum.Type.Ok,
|
||||
Configuration = new UnitConfiguration
|
||||
// Arrange
|
||||
var unit = new Unit
|
||||
{
|
||||
AutoAdt = true,
|
||||
},
|
||||
AltableOptionListId = ObjectId.GenerateNewId(),
|
||||
AllergyListId = ObjectId.GenerateNewId()
|
||||
};
|
||||
|
||||
// Act
|
||||
var insertResult = await _repository.InsertOneUnit(unit);
|
||||
var findResult = await _repository.FindById(unit.Id);
|
||||
|
||||
// Assert
|
||||
Assert.That(insertResult, Is.Not.Null);
|
||||
Assert.That(findResult, Is.Not.Null);
|
||||
Assert.That(findResult?.Id, Is.EqualTo(unit.Id));
|
||||
Assert.That(findResult?.Title, Is.EqualTo(unit.Title));
|
||||
Assert.That(findResult?.Name, Is.EqualTo(unit.Name));
|
||||
}
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Title = "Test Unit",
|
||||
Name = "Test Unit",
|
||||
LastUpdate = DateTime.UtcNow,
|
||||
PointOfCareIds = [ObjectId.GenerateNewId()],
|
||||
Status = StatusEnum.Type.Ok,
|
||||
Configuration = new UnitConfiguration
|
||||
{
|
||||
AutoAdt = true,
|
||||
},
|
||||
AltableOptionListId = ObjectId.GenerateNewId(),
|
||||
AllergyListId = ObjectId.GenerateNewId()
|
||||
};
|
||||
|
||||
// Act
|
||||
var insertResult = await _repository.InsertOneUnit(unit);
|
||||
var findResult = await _repository.FindById(unit.Id);
|
||||
|
||||
// Assert
|
||||
Assert.That(insertResult, Is.Not.Null);
|
||||
Assert.That(findResult, Is.Not.Null);
|
||||
Assert.That(findResult?.Id, Is.EqualTo(unit.Id));
|
||||
Assert.That(findResult?.Title, Is.EqualTo(unit.Title));
|
||||
Assert.That(findResult?.Name, Is.EqualTo(unit.Name));
|
||||
}
|
||||
|
||||
// [Test]
|
||||
// public async Task FindByLocation_ValidLocation_ReturnsUnit()
|
||||
@@ -116,40 +122,46 @@ public class UnitRepositoryTest
|
||||
// Assert.That(result?.Id, Is.EqualTo(unit.Id));
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that FindById retrieves the matching <see cref="Unit"/> from the repository when a valid identifier is provided.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindById_ValidId_ReturnsUnit()
|
||||
{
|
||||
// Arrange
|
||||
var unitId = ObjectId.GenerateNewId();
|
||||
var unit = new Unit
|
||||
public async Task FindById_ValidId_ReturnsUnit()
|
||||
{
|
||||
Id = unitId,
|
||||
Title = "Test Unit",
|
||||
Name = "Test Unit"
|
||||
};
|
||||
|
||||
await _repository.InsertOneUnit(unit);
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindById(unitId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result?.Id, Is.EqualTo(unitId));
|
||||
}
|
||||
// Arrange
|
||||
var unitId = ObjectId.GenerateNewId();
|
||||
var unit = new Unit
|
||||
{
|
||||
Id = unitId,
|
||||
Title = "Test Unit",
|
||||
Name = "Test Unit"
|
||||
};
|
||||
|
||||
await _repository.InsertOneUnit(unit);
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindById(unitId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result?.Id, Is.EqualTo(unitId));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that FindById returns <c>null</c> when queried with an ID that does not exist in the repository.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindById_InvalidId_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
var invalidId = ObjectId.GenerateNewId();
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindById(invalidId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
public async Task FindById_InvalidId_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
var invalidId = ObjectId.GenerateNewId();
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindById(invalidId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
// [Test]
|
||||
// public async Task FindByMasterListId_ValidId_ReturnsMatchingUnits()
|
||||
@@ -191,40 +203,47 @@ public class UnitRepositoryTest
|
||||
// // Add more assertions as needed
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's <c>FindByName</c> method returns the matching unit when called with a valid unit name.
|
||||
/// The test inserts a unit, retrieves it by name, and asserts that the returned entity is not null and has the expected name.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByName_ValidName_ReturnsUnit()
|
||||
{
|
||||
// Arrange
|
||||
var unitName = "TestUnit";
|
||||
var unit = new Unit
|
||||
public async Task FindByName_ValidName_ReturnsUnit()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Title = "Test Unit",
|
||||
Name = unitName
|
||||
};
|
||||
|
||||
await _repository.InsertOneUnit(unit);
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindByName(unitName);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result?.Name, Is.EqualTo(unitName));
|
||||
}
|
||||
// Arrange
|
||||
var unitName = "TestUnit";
|
||||
var unit = new Unit
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Title = "Test Unit",
|
||||
Name = unitName
|
||||
};
|
||||
|
||||
await _repository.InsertOneUnit(unit);
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindByName(unitName);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result?.Name, Is.EqualTo(unitName));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the repository's FindByName method returns null when invoked with a name that does not match any existing entity.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByName_InvalidName_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
var invalidName = "NonExistentUnitName";
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindByName(invalidName);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
public async Task FindByName_InvalidName_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
var invalidName = "NonExistentUnitName";
|
||||
|
||||
// Act
|
||||
var result = await _repository.FindByName(invalidName);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
// [Test]
|
||||
// public async Task FindByPointOfCare_ValidPointOfCare_ReturnsUnit()
|
||||
@@ -323,55 +342,62 @@ public class UnitRepositoryTest
|
||||
// Assert.That(result, Is.Empty);
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>GetAll</c> returns a non-null collection containing the units that have been inserted into the repository.
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentNullException">Thrown when the <c>units</c> collection used to seed the repository is <c>null</c>.</exception>
|
||||
[Test]
|
||||
public async Task GetAll_ReturnsAllUnits()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
var units = new List<Unit>();
|
||||
if (units == null) throw new ArgumentNullException(nameof(units));
|
||||
for (var i = 0; i < 5; i++)
|
||||
public async Task GetAll_ReturnsAllUnits()
|
||||
{
|
||||
var unit = new Unit
|
||||
// Arrange
|
||||
|
||||
var units = new List<Unit>();
|
||||
if (units == null) throw new ArgumentNullException(nameof(units));
|
||||
for (var i = 0; i < 5; i++)
|
||||
{
|
||||
Id = ObjectId.GenerateNewId()
|
||||
};
|
||||
units.Add(unit);
|
||||
await _repository.InsertOneUnit(unit);
|
||||
var unit = new Unit
|
||||
{
|
||||
Id = ObjectId.GenerateNewId()
|
||||
};
|
||||
units.Add(unit);
|
||||
await _repository.InsertOneUnit(unit);
|
||||
}
|
||||
|
||||
// Act
|
||||
var result = await _repository.GetAll();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Has.Count.Not.EqualTo(0));
|
||||
}
|
||||
|
||||
// Act
|
||||
var result = await _repository.GetAll();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Has.Count.Not.EqualTo(0));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that UpdateUnit correctly updates an existing unit in the repository and returns the updated entity with the new title and the original identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task UpdateUnit_ValidUnit_ReturnsUpdatedUnit()
|
||||
{
|
||||
// Arrange
|
||||
var originalUnit = new Unit
|
||||
public async Task UpdateUnit_ValidUnit_ReturnsUpdatedUnit()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Title = "Original Title"
|
||||
};
|
||||
|
||||
var updatedUnit = new Unit
|
||||
{
|
||||
Id = originalUnit.Id,
|
||||
Title = "Updated Title"
|
||||
};
|
||||
|
||||
await _repository.InsertOneUnit(originalUnit);
|
||||
|
||||
// Act
|
||||
var result = await _repository.UpdateUnit(updatedUnit);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result?.Id, Is.EqualTo(originalUnit.Id));
|
||||
Assert.That(result?.Title, Is.EqualTo(updatedUnit.Title));
|
||||
}
|
||||
// Arrange
|
||||
var originalUnit = new Unit
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Title = "Original Title"
|
||||
};
|
||||
|
||||
var updatedUnit = new Unit
|
||||
{
|
||||
Id = originalUnit.Id,
|
||||
Title = "Updated Title"
|
||||
};
|
||||
|
||||
await _repository.InsertOneUnit(originalUnit);
|
||||
|
||||
// Act
|
||||
var result = await _repository.UpdateUnit(updatedUnit);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result?.Id, Is.EqualTo(originalUnit.Id));
|
||||
Assert.That(result?.Title, Is.EqualTo(updatedUnit.Title));
|
||||
}
|
||||
}
|
||||
@@ -11,35 +11,38 @@ namespace adas_core.Test.Repositories;
|
||||
[Category("Integration")]
|
||||
public class UserRepositoryTest
|
||||
{
|
||||
/// <summary>
|
||||
/// One-time integration test setup that prepares a clean "users" collection in the test database and seeds it with two predefined users, ensuring a deterministic state for downstream test cases.
|
||||
/// </summary>
|
||||
[OneTimeSetUp]
|
||||
public async Task Init()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var user1 = new User
|
||||
public async Task Init()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
UserName = "username1",
|
||||
Password = "password1"
|
||||
//Rol = "rol1"
|
||||
};
|
||||
|
||||
var user2 = new User
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
UserName = "username2",
|
||||
Password = "password2"
|
||||
//Rol = "rol2"
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("users");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("users");
|
||||
|
||||
_repository = new UserRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(user1);
|
||||
await _repository.InsertOneAsync(user2);
|
||||
}
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
var user1 = new User
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
UserName = "username1",
|
||||
Password = "password1"
|
||||
//Rol = "rol1"
|
||||
};
|
||||
|
||||
var user2 = new User
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
UserName = "username2",
|
||||
Password = "password2"
|
||||
//Rol = "rol2"
|
||||
};
|
||||
|
||||
await IntegrationDb.Database.DropCollectionAsync("users");
|
||||
await IntegrationDb.Database.CreateCollectionAsync("users");
|
||||
|
||||
_repository = new UserRepository(_optionsApiSettings, IntegrationDb.Database);
|
||||
|
||||
await _repository.InsertOneAsync(user1);
|
||||
await _repository.InsertOneAsync(user2);
|
||||
}
|
||||
|
||||
private UserRepository _repository = null!;
|
||||
|
||||
@@ -51,17 +54,20 @@ public class UserRepositoryTest
|
||||
private IOptions<ApiSettings> _optionsApiSettings = null!;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the <see cref="_repository"/>'s <c>GetUser</c> method asynchronously returns a non-null user with the expected username and password credentials.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetUser()
|
||||
{
|
||||
var result = await _repository.GetUser("username1", "password1");
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
using (Assert.EnterMultipleScope())
|
||||
public async Task GetUser()
|
||||
{
|
||||
Assert.That(result!.UserName, Is.EqualTo("username1"));
|
||||
Assert.That(result.Password, Is.EqualTo("password1"));
|
||||
//Assert.That(result.Rol, Is.EqualTo("rol1"));
|
||||
};
|
||||
}
|
||||
var result = await _repository.GetUser("username1", "password1");
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(result!.UserName, Is.EqualTo("username1"));
|
||||
Assert.That(result.Password, Is.EqualTo("password1"));
|
||||
//Assert.That(result.Rol, Is.EqualTo("rol1"));
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,9 @@ using Moq;
|
||||
|
||||
namespace adas_core.Test.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Contains unit tests for verifying the behavior of the <see cref="AdmissionService"/> class.
|
||||
/// </summary>
|
||||
public class AdmissionServiceTest
|
||||
{
|
||||
private Mock<IAdmissionRepository> _admissionRepositoryMock;
|
||||
@@ -78,97 +81,113 @@ public class AdmissionServiceTest
|
||||
_masterListServiceFactoryMock.Object);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the admission service successfully deletes a valid admission by ensuring the repository's
|
||||
/// Delete operation is invoked exactly once for the corresponding admission identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task DeleteAdmissionAsync_ValidAdmission_DeletesSuccessfully()
|
||||
{
|
||||
// Arrange
|
||||
var admissionId = ObjectId.GenerateNewId();
|
||||
var admission = new Admission { Id = admissionId };
|
||||
|
||||
_admissionRepositoryMock.Setup(repo => repo.FindById(admissionId))
|
||||
.ReturnsAsync(admission);
|
||||
|
||||
// Act
|
||||
await _admissionService.DeleteAdmissionAsync(admission);
|
||||
|
||||
// Assert
|
||||
_admissionRepositoryMock.Verify(repo => repo.Delete(admissionId), Times.Once);
|
||||
}
|
||||
public async Task DeleteAdmissionAsync_ValidAdmission_DeletesSuccessfully()
|
||||
{
|
||||
// Arrange
|
||||
var admissionId = ObjectId.GenerateNewId();
|
||||
var admission = new Admission { Id = admissionId };
|
||||
|
||||
_admissionRepositoryMock.Setup(repo => repo.FindById(admissionId))
|
||||
.ReturnsAsync(admission);
|
||||
|
||||
// Act
|
||||
await _admissionService.DeleteAdmissionAsync(admission);
|
||||
|
||||
// Assert
|
||||
_admissionRepositoryMock.Verify(repo => repo.Delete(admissionId), Times.Once);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>DeleteAdmissionByIdAsync</c> successfully deletes an admission when it exists in the repository, by ensuring the repository's <c>Delete</c> method is invoked exactly once for the given admission identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task DeleteAdmissionByIdAsync_AdmissionExists_DeletesSuccessfully()
|
||||
{
|
||||
// Arrange
|
||||
var admissionId = ObjectId.GenerateNewId();
|
||||
var admission = new Admission { Id = admissionId, PointOfCareId = ObjectId.GenerateNewId() };
|
||||
|
||||
_admissionRepositoryMock.Setup(repo => repo.FindById(admissionId))
|
||||
.ReturnsAsync(admission);
|
||||
|
||||
// Act
|
||||
await _admissionService.DeleteAdmissionByIdAsync(admissionId);
|
||||
|
||||
// Assert
|
||||
_admissionRepositoryMock.Verify(repo => repo.Delete(admissionId), Times.Once);
|
||||
}
|
||||
public async Task DeleteAdmissionByIdAsync_AdmissionExists_DeletesSuccessfully()
|
||||
{
|
||||
// Arrange
|
||||
var admissionId = ObjectId.GenerateNewId();
|
||||
var admission = new Admission { Id = admissionId, PointOfCareId = ObjectId.GenerateNewId() };
|
||||
|
||||
_admissionRepositoryMock.Setup(repo => repo.FindById(admissionId))
|
||||
.ReturnsAsync(admission);
|
||||
|
||||
// Act
|
||||
await _admissionService.DeleteAdmissionByIdAsync(admissionId);
|
||||
|
||||
// Assert
|
||||
_admissionRepositoryMock.Verify(repo => repo.Delete(admissionId), Times.Once);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="AdmissionService.GetAdmissionByIdAsync"/> returns the admission together with its
|
||||
/// associated patient location (unit, bed, and room) when the admission exists in the repository and the
|
||||
/// corresponding point of care is successfully resolved.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetAdmissionByIdAsync_AdmissionExists_ReturnsAdmissionWithPatientLocation()
|
||||
{
|
||||
// Arrange
|
||||
var admissionId = ObjectId.GenerateNewId();
|
||||
var pointOfCareId = ObjectId.GenerateNewId();
|
||||
var admission = new Admission { Id = admissionId, PointOfCareId = pointOfCareId };
|
||||
var poc = new PointOfCare { Id = pointOfCareId, UnitName = "TestUnit", Bed = "TestBed", Room = "TestRoom" };
|
||||
|
||||
_admissionRepositoryMock.Setup(repo => repo.FindById(admissionId))
|
||||
.ReturnsAsync(admission);
|
||||
_pointOfCareServiceMock.Setup(repo => repo.GetInfo(pointOfCareId, null, false, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(poc);
|
||||
|
||||
// Act
|
||||
var result = await _admissionService.GetAdmissionByIdAsync(admissionId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result?.PatientLocation, Is.Not.Null);
|
||||
Assert.That(result?.PatientLocation?.UnitName, Is.EqualTo("TestUnit"));
|
||||
Assert.That(result?.PatientLocation?.Bed, Is.EqualTo("TestBed"));
|
||||
Assert.That(result?.PatientLocation?.Room, Is.EqualTo("TestRoom"));
|
||||
}
|
||||
public async Task GetAdmissionByIdAsync_AdmissionExists_ReturnsAdmissionWithPatientLocation()
|
||||
{
|
||||
// Arrange
|
||||
var admissionId = ObjectId.GenerateNewId();
|
||||
var pointOfCareId = ObjectId.GenerateNewId();
|
||||
var admission = new Admission { Id = admissionId, PointOfCareId = pointOfCareId };
|
||||
var poc = new PointOfCare { Id = pointOfCareId, UnitName = "TestUnit", Bed = "TestBed", Room = "TestRoom" };
|
||||
|
||||
_admissionRepositoryMock.Setup(repo => repo.FindById(admissionId))
|
||||
.ReturnsAsync(admission);
|
||||
_pointOfCareServiceMock.Setup(repo => repo.GetInfo(pointOfCareId, null, false, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(poc);
|
||||
|
||||
// Act
|
||||
var result = await _admissionService.GetAdmissionByIdAsync(admissionId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result?.PatientLocation, Is.Not.Null);
|
||||
Assert.That(result?.PatientLocation?.UnitName, Is.EqualTo("TestUnit"));
|
||||
Assert.That(result?.PatientLocation?.Bed, Is.EqualTo("TestBed"));
|
||||
Assert.That(result?.PatientLocation?.Room, Is.EqualTo("TestRoom"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that GetAdmissionsAsync returns admissions enriched with their associated patient location details
|
||||
/// retrieved from the point of care service.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetAdmissionsAsync_ReturnsAdmissionsWithPatientLocations()
|
||||
{
|
||||
// Arrange
|
||||
var admission1Id = ObjectId.GenerateNewId();
|
||||
var admission2Id = ObjectId.GenerateNewId();
|
||||
var poc1Id = ObjectId.GenerateNewId();
|
||||
var poc2Id = ObjectId.GenerateNewId();
|
||||
var admission1 = new Admission { Id = admission1Id, PointOfCareId = poc1Id };
|
||||
var admission2 = new Admission { Id = admission2Id, PointOfCareId = poc2Id };
|
||||
var admissionsList = new List<Admission> { admission1, admission2 };
|
||||
|
||||
_admissionRepositoryMock.Setup(repo => repo.FindAll())
|
||||
.ReturnsAsync(admissionsList);
|
||||
_pointOfCareServiceMock.Setup(repo => repo.GetInfo(poc1Id, null, false, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(TestUtilities.CreateValidPointOfCare());
|
||||
_pointOfCareServiceMock.Setup(repo => repo.GetInfo(poc2Id, null, false, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(TestUtilities.CreateValidPointOfCare());
|
||||
|
||||
// Act
|
||||
var result = await _admissionService.GetAdmissionsAsync();
|
||||
|
||||
// Assert
|
||||
var admissions = result.ToList();
|
||||
Assert.That(admissions, Is.Not.Null);
|
||||
Assert.That(admissions.Count(), Is.EqualTo(2));
|
||||
var admissionArray = admissions.ToArray();
|
||||
Assert.That(admissionArray.First().PatientLocation, Is.Not.Null);
|
||||
Assert.That(admissionArray.First().PatientLocation?.UnitName, Is.EqualTo("Test Unit"));
|
||||
Assert.That(admissionArray.First().PatientLocation?.Bed, Is.EqualTo("Test Bed"));
|
||||
Assert.That(admissionArray.First().PatientLocation?.Room, Is.EqualTo("Test Room"));
|
||||
}
|
||||
public async Task GetAdmissionsAsync_ReturnsAdmissionsWithPatientLocations()
|
||||
{
|
||||
// Arrange
|
||||
var admission1Id = ObjectId.GenerateNewId();
|
||||
var admission2Id = ObjectId.GenerateNewId();
|
||||
var poc1Id = ObjectId.GenerateNewId();
|
||||
var poc2Id = ObjectId.GenerateNewId();
|
||||
var admission1 = new Admission { Id = admission1Id, PointOfCareId = poc1Id };
|
||||
var admission2 = new Admission { Id = admission2Id, PointOfCareId = poc2Id };
|
||||
var admissionsList = new List<Admission> { admission1, admission2 };
|
||||
|
||||
_admissionRepositoryMock.Setup(repo => repo.FindAll())
|
||||
.ReturnsAsync(admissionsList);
|
||||
_pointOfCareServiceMock.Setup(repo => repo.GetInfo(poc1Id, null, false, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(TestUtilities.CreateValidPointOfCare());
|
||||
_pointOfCareServiceMock.Setup(repo => repo.GetInfo(poc2Id, null, false, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(TestUtilities.CreateValidPointOfCare());
|
||||
|
||||
// Act
|
||||
var result = await _admissionService.GetAdmissionsAsync();
|
||||
|
||||
// Assert
|
||||
var admissions = result.ToList();
|
||||
Assert.That(admissions, Is.Not.Null);
|
||||
Assert.That(admissions.Count(), Is.EqualTo(2));
|
||||
var admissionArray = admissions.ToArray();
|
||||
Assert.That(admissionArray.First().PatientLocation, Is.Not.Null);
|
||||
Assert.That(admissionArray.First().PatientLocation?.UnitName, Is.EqualTo("Test Unit"));
|
||||
Assert.That(admissionArray.First().PatientLocation?.Bed, Is.EqualTo("Test Bed"));
|
||||
Assert.That(admissionArray.First().PatientLocation?.Room, Is.EqualTo("Test Room"));
|
||||
}
|
||||
|
||||
// [Test]
|
||||
// public async Task InsertAdmission_WhenPointOfCareExists_InsertsAdmission()
|
||||
@@ -205,224 +224,255 @@ public class AdmissionServiceTest
|
||||
// pointOfCareServiceMock.Verify(repo => repo.Update(It.IsAny<PointOfCare>()), Times.Once);
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="_admissionService"/>.UpdateAdmissionAsync correctly updates an existing admission by
|
||||
/// invoking the repository's Update method and retrieving point-of-care information for both the new and the
|
||||
/// previous point of care associated with the admission.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task UpdateAdmissionAsync_WhenAdmissionExists_UpdatesAdmission()
|
||||
{
|
||||
// Arrange
|
||||
var admissionId = ObjectId.GenerateNewId();
|
||||
var admission = new Admission
|
||||
public async Task UpdateAdmissionAsync_WhenAdmissionExists_UpdatesAdmission()
|
||||
{
|
||||
Id = admissionId,
|
||||
AdmissionDate = DateTime.UtcNow,
|
||||
Nhc = "TestNhc",
|
||||
PointOfCareId = ObjectId.GenerateNewId(),
|
||||
Person = new Person(),
|
||||
Origin = TestUtilities.CreateValidOptionList(),
|
||||
Diagnosis = TestUtilities.CreateValidOptionList(),
|
||||
Allergies = [TestUtilities.CreateValidOptionList()],
|
||||
Insulation = TestUtilities.CreateValidOptionList(),
|
||||
LanguageBarrier = [TestUtilities.CreateValidOptionList()]
|
||||
};
|
||||
|
||||
var oldAdmission = new Admission
|
||||
{
|
||||
Id = admissionId,
|
||||
AdmissionDate = DateTime.UtcNow.AddDays(-1), // Update admission date
|
||||
Nhc = "OldNhc",
|
||||
PointOfCareId = ObjectId.GenerateNewId(), // Change PointOfCareId
|
||||
Person = new Person(),
|
||||
Origin = TestUtilities.CreateValidOptionList(),
|
||||
Diagnosis = TestUtilities.CreateValidOptionList(),
|
||||
Allergies = [TestUtilities.CreateValidOptionList()],
|
||||
Insulation = TestUtilities.CreateValidOptionList(),
|
||||
LanguageBarrier = [TestUtilities.CreateValidOptionList()]
|
||||
};
|
||||
|
||||
_admissionRepositoryMock
|
||||
.Setup(repo => repo.FindById(admissionId))
|
||||
.ReturnsAsync(oldAdmission);
|
||||
|
||||
var updatedPointOfCare = TestUtilities.CreateValidPointOfCare();
|
||||
_pointOfCareServiceMock
|
||||
.Setup(repo => repo.GetInfo(admission.PointOfCareId.Value, null, false, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(updatedPointOfCare);
|
||||
|
||||
// Act
|
||||
await _admissionService.UpdateAdmissionAsync(admission);
|
||||
|
||||
// Assert
|
||||
_admissionRepositoryMock.Verify(repo => repo.Update(admission), Times.Once);
|
||||
_pointOfCareServiceMock.Verify(repo => repo.GetInfo(admission.PointOfCareId.Value, null, false, It.IsAny<CancellationToken>()), Times.Once);
|
||||
_pointOfCareServiceMock.Verify(repo => repo.GetInfo(oldAdmission.PointOfCareId.Value, null, false, It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task AdmitPatient_WithValidAdmission_CreatesPatientAndDeletesAdmission()
|
||||
{
|
||||
// Arrange
|
||||
var admission = TestUtilities.CreateValidAdmission();
|
||||
var unit = TestUtilities.CreateValidUnit();
|
||||
var pointOfCare = TestUtilities.CreateValidPointOfCare();
|
||||
|
||||
|
||||
_unitServiceMock
|
||||
.Setup(repo => repo.FindById(admission.UnitId))
|
||||
.ReturnsAsync(unit);
|
||||
|
||||
_pointOfCareServiceMock
|
||||
.Setup(repo => repo.FindById(It.IsAny<ObjectId>()))
|
||||
.ReturnsAsync((ObjectId id) => id == admission.PointOfCareId ? pointOfCare : null);
|
||||
|
||||
|
||||
// Act
|
||||
await _admissionService.AdmitPatient(admission);
|
||||
|
||||
// Assert
|
||||
_patientServiceMock.Verify(repo => repo.Insert(It.IsAny<Patient>()), Times.Once);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetAdmissionByLocation_LocationExists_ReturnsAdmissions()
|
||||
{
|
||||
// Arrange
|
||||
var location = new PatientLocation
|
||||
{
|
||||
UnitName = "Test Unit",
|
||||
Bed = "Test Bed",
|
||||
Room = "Test Room"
|
||||
};
|
||||
var expectedAdmissions = new List<Admission>
|
||||
{
|
||||
new() { Id = ObjectId.GenerateNewId() },
|
||||
new() { Id = ObjectId.GenerateNewId() }
|
||||
};
|
||||
|
||||
_admissionRepositoryMock.Setup(repo => repo.FindByLocation(location))
|
||||
.ReturnsAsync(expectedAdmissions);
|
||||
|
||||
// Act
|
||||
var result = await _admissionService.GetAdmissionByLocation(location);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.EqualTo(expectedAdmissions));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetAdmissionByLocation_LocationNotFound_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
var location = new PatientLocation
|
||||
{
|
||||
UnitName = "Nonexistent Unit",
|
||||
Bed = "Nonexistent Bed",
|
||||
Room = "Nonexistent Room"
|
||||
};
|
||||
|
||||
_admissionRepositoryMock.Setup(repo => repo.FindByLocation(location))
|
||||
.ThrowsAsync(new Exception());
|
||||
|
||||
// Act
|
||||
var result = await _admissionService.GetAdmissionByLocation(location);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetAdmissionByPointOfCareId_POCExists_ReturnsAdmissionsWithLocation()
|
||||
{
|
||||
// Arrange
|
||||
var pocId = ObjectId.GenerateNewId();
|
||||
var expectedAdmissions = new List<Admission>
|
||||
{
|
||||
new() { Id = ObjectId.GenerateNewId() },
|
||||
new() { Id = ObjectId.GenerateNewId() }
|
||||
};
|
||||
var poc = new PointOfCare
|
||||
{
|
||||
Id = pocId,
|
||||
UnitName = "Test Unit",
|
||||
Bed = "Test Bed",
|
||||
Room = "Test Room"
|
||||
};
|
||||
|
||||
_admissionRepositoryMock.Setup(repo => repo.FindByPointOfCareId(pocId))
|
||||
.ReturnsAsync(expectedAdmissions);
|
||||
|
||||
_pointOfCareServiceMock.Setup(repo => repo.GetInfo(pocId, null, false, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(poc);
|
||||
|
||||
// Act
|
||||
var result = await _admissionService.GetAdmissionByPointOfCareId(pocId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Count, Is.EqualTo(expectedAdmissions.Count));
|
||||
|
||||
foreach (var admission in result)
|
||||
{
|
||||
Assert.That(admission.PatientLocation, Is.Not.Null);
|
||||
Assert.That(admission.PatientLocation?.UnitName, Is.EqualTo(poc.UnitName));
|
||||
Assert.That(admission.PatientLocation?.Bed, Is.EqualTo(poc.Bed));
|
||||
Assert.That(admission.PatientLocation?.Room, Is.EqualTo(poc.Room));
|
||||
// Arrange
|
||||
var admissionId = ObjectId.GenerateNewId();
|
||||
var admission = new Admission
|
||||
{
|
||||
Id = admissionId,
|
||||
AdmissionDate = DateTime.UtcNow,
|
||||
Nhc = "TestNhc",
|
||||
PointOfCareId = ObjectId.GenerateNewId(),
|
||||
Person = new Person(),
|
||||
Origin = TestUtilities.CreateValidOptionList(),
|
||||
Diagnosis = TestUtilities.CreateValidOptionList(),
|
||||
Allergies = [TestUtilities.CreateValidOptionList()],
|
||||
Insulation = TestUtilities.CreateValidOptionList(),
|
||||
LanguageBarrier = [TestUtilities.CreateValidOptionList()]
|
||||
};
|
||||
|
||||
var oldAdmission = new Admission
|
||||
{
|
||||
Id = admissionId,
|
||||
AdmissionDate = DateTime.UtcNow.AddDays(-1), // Update admission date
|
||||
Nhc = "OldNhc",
|
||||
PointOfCareId = ObjectId.GenerateNewId(), // Change PointOfCareId
|
||||
Person = new Person(),
|
||||
Origin = TestUtilities.CreateValidOptionList(),
|
||||
Diagnosis = TestUtilities.CreateValidOptionList(),
|
||||
Allergies = [TestUtilities.CreateValidOptionList()],
|
||||
Insulation = TestUtilities.CreateValidOptionList(),
|
||||
LanguageBarrier = [TestUtilities.CreateValidOptionList()]
|
||||
};
|
||||
|
||||
_admissionRepositoryMock
|
||||
.Setup(repo => repo.FindById(admissionId))
|
||||
.ReturnsAsync(oldAdmission);
|
||||
|
||||
var updatedPointOfCare = TestUtilities.CreateValidPointOfCare();
|
||||
_pointOfCareServiceMock
|
||||
.Setup(repo => repo.GetInfo(admission.PointOfCareId.Value, null, false, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(updatedPointOfCare);
|
||||
|
||||
// Act
|
||||
await _admissionService.UpdateAdmissionAsync(admission);
|
||||
|
||||
// Assert
|
||||
_admissionRepositoryMock.Verify(repo => repo.Update(admission), Times.Once);
|
||||
_pointOfCareServiceMock.Verify(repo => repo.GetInfo(admission.PointOfCareId.Value, null, false, It.IsAny<CancellationToken>()), Times.Once);
|
||||
_pointOfCareServiceMock.Verify(repo => repo.GetInfo(oldAdmission.PointOfCareId.Value, null, false, It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that admitting a patient with a valid admission—where the associated unit is found and the point of care matches—results in a new patient being inserted.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetAdmissionByPointOfCareId_POCNotFound_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
var pocId = ObjectId.GenerateNewId();
|
||||
|
||||
_admissionRepositoryMock.Setup(repo => repo.FindByPointOfCareId(pocId))
|
||||
.ThrowsAsync(new Exception("Repository error"));
|
||||
|
||||
// Act
|
||||
var result = await _admissionService.GetAdmissionByPointOfCareId(pocId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetAdmissionByUnitIdWithOutPoC_UnitIdExists_ReturnsAdmissions()
|
||||
{
|
||||
// Arrange
|
||||
var unitId = ObjectId.GenerateNewId();
|
||||
var expectedAdmissions = new List<Admission>
|
||||
public async Task AdmitPatient_WithValidAdmission_CreatesPatientAndDeletesAdmission()
|
||||
{
|
||||
new() { Id = ObjectId.GenerateNewId() },
|
||||
new() { Id = ObjectId.GenerateNewId() }
|
||||
};
|
||||
|
||||
_admissionRepositoryMock.Setup(repo => repo.GetAdmissionByUnitIdWithOutPoC(unitId))
|
||||
.ReturnsAsync(expectedAdmissions);
|
||||
|
||||
// Act
|
||||
var result = await _admissionService.GetAdmissionByUnitIdWithOutPoC(unitId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Count, Is.EqualTo(expectedAdmissions.Count));
|
||||
Assert.That(result, Is.EqualTo(expectedAdmissions));
|
||||
}
|
||||
// Arrange
|
||||
var admission = TestUtilities.CreateValidAdmission();
|
||||
var unit = TestUtilities.CreateValidUnit();
|
||||
var pointOfCare = TestUtilities.CreateValidPointOfCare();
|
||||
|
||||
|
||||
_unitServiceMock
|
||||
.Setup(repo => repo.FindById(admission.UnitId))
|
||||
.ReturnsAsync(unit);
|
||||
|
||||
_pointOfCareServiceMock
|
||||
.Setup(repo => repo.FindById(It.IsAny<ObjectId>()))
|
||||
.ReturnsAsync((ObjectId id) => id == admission.PointOfCareId ? pointOfCare : null);
|
||||
|
||||
|
||||
// Act
|
||||
await _admissionService.AdmitPatient(admission);
|
||||
|
||||
// Assert
|
||||
_patientServiceMock.Verify(repo => repo.Insert(It.IsAny<Patient>()), Times.Once);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that GetAdmissionByLocation returns the expected list of admissions when a matching patient location is found, confirming the service correctly retrieves results from the repository.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetAdmissionByUnitIdWithOutPoC_UnitIdNotFound_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
var unitId = ObjectId.GenerateNewId();
|
||||
public async Task GetAdmissionByLocation_LocationExists_ReturnsAdmissions()
|
||||
{
|
||||
// Arrange
|
||||
var location = new PatientLocation
|
||||
{
|
||||
UnitName = "Test Unit",
|
||||
Bed = "Test Bed",
|
||||
Room = "Test Room"
|
||||
};
|
||||
var expectedAdmissions = new List<Admission>
|
||||
{
|
||||
new() { Id = ObjectId.GenerateNewId() },
|
||||
new() { Id = ObjectId.GenerateNewId() }
|
||||
};
|
||||
|
||||
_admissionRepositoryMock.Setup(repo => repo.FindByLocation(location))
|
||||
.ReturnsAsync(expectedAdmissions);
|
||||
|
||||
// Act
|
||||
var result = await _admissionService.GetAdmissionByLocation(location);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.EqualTo(expectedAdmissions));
|
||||
}
|
||||
|
||||
_admissionRepositoryMock.Setup(repo => repo.GetAdmissionByUnitIdWithOutPoC(unitId))
|
||||
.ThrowsAsync(new Exception("Repository error"));
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="AdmissionService.GetAdmissionByLocation"/> returns an empty result when the requested location does not exist, simulating the not-found scenario by having the repository throw an exception.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetAdmissionByLocation_LocationNotFound_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
var location = new PatientLocation
|
||||
{
|
||||
UnitName = "Nonexistent Unit",
|
||||
Bed = "Nonexistent Bed",
|
||||
Room = "Nonexistent Room"
|
||||
};
|
||||
|
||||
_admissionRepositoryMock.Setup(repo => repo.FindByLocation(location))
|
||||
.ThrowsAsync(new Exception());
|
||||
|
||||
// Act
|
||||
var result = await _admissionService.GetAdmissionByLocation(location);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
|
||||
// Act
|
||||
var result = await _admissionService.GetAdmissionByUnitIdWithOutPoC(unitId);
|
||||
/// <summary>
|
||||
/// Verifies that when a Point of Care exists for the given identifier, the admissions returned by
|
||||
/// <c>GetAdmissionByPointOfCareId</c> are enriched with patient location details (unit name, bed, and room)
|
||||
/// retrieved from the corresponding Point of Care entity.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetAdmissionByPointOfCareId_POCExists_ReturnsAdmissionsWithLocation()
|
||||
{
|
||||
// Arrange
|
||||
var pocId = ObjectId.GenerateNewId();
|
||||
var expectedAdmissions = new List<Admission>
|
||||
{
|
||||
new() { Id = ObjectId.GenerateNewId() },
|
||||
new() { Id = ObjectId.GenerateNewId() }
|
||||
};
|
||||
var poc = new PointOfCare
|
||||
{
|
||||
Id = pocId,
|
||||
UnitName = "Test Unit",
|
||||
Bed = "Test Bed",
|
||||
Room = "Test Room"
|
||||
};
|
||||
|
||||
_admissionRepositoryMock.Setup(repo => repo.FindByPointOfCareId(pocId))
|
||||
.ReturnsAsync(expectedAdmissions);
|
||||
|
||||
_pointOfCareServiceMock.Setup(repo => repo.GetInfo(pocId, null, false, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(poc);
|
||||
|
||||
// Act
|
||||
var result = await _admissionService.GetAdmissionByPointOfCareId(pocId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Count, Is.EqualTo(expectedAdmissions.Count));
|
||||
|
||||
foreach (var admission in result)
|
||||
{
|
||||
Assert.That(admission.PatientLocation, Is.Not.Null);
|
||||
Assert.That(admission.PatientLocation?.UnitName, Is.EqualTo(poc.UnitName));
|
||||
Assert.That(admission.PatientLocation?.Bed, Is.EqualTo(poc.Bed));
|
||||
Assert.That(admission.PatientLocation?.Room, Is.EqualTo(poc.Room));
|
||||
}
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="AdmissionService.GetAdmissionByPointOfCareId"/> returns an empty result when the underlying repository throws an exception while attempting to find an admission by point of care id.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetAdmissionByPointOfCareId_POCNotFound_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
var pocId = ObjectId.GenerateNewId();
|
||||
|
||||
_admissionRepositoryMock.Setup(repo => repo.FindByPointOfCareId(pocId))
|
||||
.ThrowsAsync(new Exception("Repository error"));
|
||||
|
||||
// Act
|
||||
var result = await _admissionService.GetAdmissionByPointOfCareId(pocId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="AdmissionService.GetAdmissionByUnitIdWithOutPoC"/> returns the expected list of admissions
|
||||
/// when a valid unit identifier is provided.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetAdmissionByUnitIdWithOutPoC_UnitIdExists_ReturnsAdmissions()
|
||||
{
|
||||
// Arrange
|
||||
var unitId = ObjectId.GenerateNewId();
|
||||
var expectedAdmissions = new List<Admission>
|
||||
{
|
||||
new() { Id = ObjectId.GenerateNewId() },
|
||||
new() { Id = ObjectId.GenerateNewId() }
|
||||
};
|
||||
|
||||
_admissionRepositoryMock.Setup(repo => repo.GetAdmissionByUnitIdWithOutPoC(unitId))
|
||||
.ReturnsAsync(expectedAdmissions);
|
||||
|
||||
// Act
|
||||
var result = await _admissionService.GetAdmissionByUnitIdWithOutPoC(unitId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Count, Is.EqualTo(expectedAdmissions.Count));
|
||||
Assert.That(result, Is.EqualTo(expectedAdmissions));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>GetAdmissionByUnitIdWithOutPoC</c> returns an empty result when the underlying repository
|
||||
/// throws an exception while looking up the given unit identifier.
|
||||
/// </summary>
|
||||
/// <param name="unitId">The identifier of the unit whose admission record is being requested.</param>
|
||||
[Test]
|
||||
public async Task GetAdmissionByUnitIdWithOutPoC_UnitIdNotFound_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
var unitId = ObjectId.GenerateNewId();
|
||||
|
||||
_admissionRepositoryMock.Setup(repo => repo.GetAdmissionByUnitIdWithOutPoC(unitId))
|
||||
.ThrowsAsync(new Exception("Repository error"));
|
||||
|
||||
// Act
|
||||
var result = await _admissionService.GetAdmissionByUnitIdWithOutPoC(unitId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
|
||||
// [Test]
|
||||
// public async Task SaveRequest_NewAdmission_ValidRequest_InsertsAdmission()
|
||||
@@ -523,52 +573,55 @@ public class AdmissionServiceTest
|
||||
// admissionServiceMock.Verify(service => service.SaveRequest(apiRequest), Times.Once);
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that InsertAdmission throws a NotFoundException and performs no insert or update operations when a required associated resource is not found while processing a valid admission.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task InsertAdmission_ValidAdmission_InsertsSuccessfullyWithUser()
|
||||
{
|
||||
// Arrange
|
||||
var admission = new Admission
|
||||
public async Task InsertAdmission_ValidAdmission_InsertsSuccessfullyWithUser()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
AdmissionDate = DateTime.UtcNow,
|
||||
Nhc = "TestNhc",
|
||||
PointOfCareId = ObjectId.GenerateNewId(),
|
||||
Person = new Person(),
|
||||
Origin = new OptionList(),
|
||||
Diagnosis = new OptionList(),
|
||||
Allergies = [new OptionList()],
|
||||
Insulation = new OptionList(),
|
||||
LanguageBarrier = [new OptionList()]
|
||||
};
|
||||
|
||||
var pointOfCare = TestUtilities.CreateValidPointOfCare();
|
||||
|
||||
_admissionRepositoryMock
|
||||
.Setup(repo => repo.FindByNhc(admission.Nhc))
|
||||
.ReturnsAsync((Admission?)null);
|
||||
|
||||
_pointOfCareServiceMock
|
||||
.Setup(repo => repo.GetInfo(admission.PointOfCareId.Value, null, false, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(pointOfCare);
|
||||
|
||||
_admissionRepositoryMock
|
||||
.Setup(repo => repo.InsertOneAsyncAndReturn(admission))
|
||||
.ReturnsAsync(admission);
|
||||
|
||||
Func<Task> act = () => _admissionService.InsertAdmission(admission);
|
||||
|
||||
var ex = Assert.ThrowsAsync<NotFoundException>(act);
|
||||
|
||||
Assert.That(ex!.Message,
|
||||
Is.EqualTo(((int)HttpEnum.ErrorMessage.NotFoundResourceMissing).ToString()));
|
||||
|
||||
// Verify no insert
|
||||
_admissionRepositoryMock
|
||||
.Verify(repo => repo.InsertOneAsyncAndReturn(It.IsAny<Admission>()), Times.Never);
|
||||
|
||||
// Verify no update
|
||||
_pointOfCareServiceMock
|
||||
.Verify(service => service.Update(It.IsAny<PointOfCare>()), Times.Never);
|
||||
}
|
||||
// Arrange
|
||||
var admission = new Admission
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
AdmissionDate = DateTime.UtcNow,
|
||||
Nhc = "TestNhc",
|
||||
PointOfCareId = ObjectId.GenerateNewId(),
|
||||
Person = new Person(),
|
||||
Origin = new OptionList(),
|
||||
Diagnosis = new OptionList(),
|
||||
Allergies = [new OptionList()],
|
||||
Insulation = new OptionList(),
|
||||
LanguageBarrier = [new OptionList()]
|
||||
};
|
||||
|
||||
var pointOfCare = TestUtilities.CreateValidPointOfCare();
|
||||
|
||||
_admissionRepositoryMock
|
||||
.Setup(repo => repo.FindByNhc(admission.Nhc))
|
||||
.ReturnsAsync((Admission?)null);
|
||||
|
||||
_pointOfCareServiceMock
|
||||
.Setup(repo => repo.GetInfo(admission.PointOfCareId.Value, null, false, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(pointOfCare);
|
||||
|
||||
_admissionRepositoryMock
|
||||
.Setup(repo => repo.InsertOneAsyncAndReturn(admission))
|
||||
.ReturnsAsync(admission);
|
||||
|
||||
Func<Task> act = () => _admissionService.InsertAdmission(admission);
|
||||
|
||||
var ex = Assert.ThrowsAsync<NotFoundException>(act);
|
||||
|
||||
Assert.That(ex!.Message,
|
||||
Is.EqualTo(((int)HttpEnum.ErrorMessage.NotFoundResourceMissing).ToString()));
|
||||
|
||||
// Verify no insert
|
||||
_admissionRepositoryMock
|
||||
.Verify(repo => repo.InsertOneAsyncAndReturn(It.IsAny<Admission>()), Times.Never);
|
||||
|
||||
// Verify no update
|
||||
_pointOfCareServiceMock
|
||||
.Verify(service => service.Update(It.IsAny<PointOfCare>()), Times.Never);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,6 +14,9 @@ using Options = Microsoft.Extensions.Options.Options;
|
||||
|
||||
namespace adas_core.Test.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Contains unit tests for verifying the behavior and functionality of the <see cref="AlarmService"/> class.
|
||||
/// </summary>
|
||||
public class AlarmServiceTest
|
||||
{
|
||||
private readonly Mock<IAlarmRepository> _alarmRepositoryMock;
|
||||
@@ -111,137 +114,154 @@ public class AlarmServiceTest
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that when an ORU_R40 type request is processed without any alarms, the patient is located but the observation is not persisted.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task SaveRequest_Oru_R40_Type_Without_Alarms_Dont_Insert()
|
||||
{
|
||||
// Arrange
|
||||
var apiRequest = new ApiRequest
|
||||
public async Task SaveRequest_Oru_R40_Type_Without_Alarms_Dont_Insert()
|
||||
{
|
||||
Type = "ORU_R40",
|
||||
PatientNumber = "12345",
|
||||
Observation = new PatientObservation { Value = "Test" },
|
||||
Alarms = [],
|
||||
Location = new PatientLocation { Bed = "Bed1", Room = "Bed1", UnitName = "Unit1" }
|
||||
};
|
||||
var unit = new Unit { Configuration = new UnitConfiguration { AutoAdt = true } };
|
||||
var patient = new Patient { Id = ObjectId.GenerateNewId(), Bed = "Bed1" };
|
||||
_unitServiceMock.Setup(u => u.FindByUnitNameOrPocName(It.IsAny<string>(), It.IsAny<string>()))
|
||||
.ReturnsAsync(unit);
|
||||
_patientServiceMock.Setup(p => p.FindPatientByApiRequest(apiRequest)).ReturnsAsync(patient);
|
||||
_observationServiceMock.Setup(o => o.SaveRequestAsync(It.IsAny<ApiRequest>())).Returns(Task.CompletedTask);
|
||||
|
||||
// Act
|
||||
await _alarmService.SaveRequest(apiRequest);
|
||||
|
||||
// Assert
|
||||
_patientServiceMock.Verify(p => p.FindPatientByApiRequest(apiRequest), Times.Once);
|
||||
_observationServiceMock.Verify(o => o.SaveRequestAsync(It.IsAny<ApiRequest>()), Times.Never);
|
||||
}
|
||||
// Arrange
|
||||
var apiRequest = new ApiRequest
|
||||
{
|
||||
Type = "ORU_R40",
|
||||
PatientNumber = "12345",
|
||||
Observation = new PatientObservation { Value = "Test" },
|
||||
Alarms = [],
|
||||
Location = new PatientLocation { Bed = "Bed1", Room = "Bed1", UnitName = "Unit1" }
|
||||
};
|
||||
var unit = new Unit { Configuration = new UnitConfiguration { AutoAdt = true } };
|
||||
var patient = new Patient { Id = ObjectId.GenerateNewId(), Bed = "Bed1" };
|
||||
_unitServiceMock.Setup(u => u.FindByUnitNameOrPocName(It.IsAny<string>(), It.IsAny<string>()))
|
||||
.ReturnsAsync(unit);
|
||||
_patientServiceMock.Setup(p => p.FindPatientByApiRequest(apiRequest)).ReturnsAsync(patient);
|
||||
_observationServiceMock.Setup(o => o.SaveRequestAsync(It.IsAny<ApiRequest>())).Returns(Task.CompletedTask);
|
||||
|
||||
// Act
|
||||
await _alarmService.SaveRequest(apiRequest);
|
||||
|
||||
// Assert
|
||||
_patientServiceMock.Verify(p => p.FindPatientByApiRequest(apiRequest), Times.Once);
|
||||
_observationServiceMock.Verify(o => o.SaveRequestAsync(It.IsAny<ApiRequest>()), Times.Never);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="AlarmService.ProcessAlarmObservations"/> inserts the provided alarm observations into the alarm repository.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ProcessAlarmObservations_Should_Insert_Alarm_Observations()
|
||||
{
|
||||
// Arrange
|
||||
var patient = new Patient { Id = ObjectId.GenerateNewId(), Bed = "Bed1" };
|
||||
var alarmObservations = new List<PatientObservationAlarm>
|
||||
public async Task ProcessAlarmObservations_Should_Insert_Alarm_Observations()
|
||||
{
|
||||
new() { Value = "Alarm1", Time = DateTime.UtcNow}
|
||||
};
|
||||
var observations = new List<PatientObservation>
|
||||
{
|
||||
new() { Value = "Alarm1", Time = DateTime.MinValue}
|
||||
};
|
||||
|
||||
_configObservationServiceMock.Setup(o => o.Map(It.IsAny<PatientObservationAlarm>(), It.IsAny<bool>()))
|
||||
.ReturnsAsync((PatientObservationAlarm obs, bool _) => obs); // Correct setup
|
||||
|
||||
_calculatedObservationsServiceMock.Setup(o => o.Map(It.IsAny<PatientObservationAlarm>(), It.IsAny<bool>()))
|
||||
.ReturnsAsync((PatientObservationAlarm obs, bool _) => obs); // Correct setup
|
||||
|
||||
// Act
|
||||
await _alarmService.ProcessAlarmObservations(alarmObservations, observations, patient, DateTime.UtcNow);
|
||||
|
||||
// Assert
|
||||
_alarmRepositoryMock.Verify(a => a.InsertOneAsync(It.IsAny<PatientObservationAlarm>()), Times.Once);
|
||||
}
|
||||
// Arrange
|
||||
var patient = new Patient { Id = ObjectId.GenerateNewId(), Bed = "Bed1" };
|
||||
var alarmObservations = new List<PatientObservationAlarm>
|
||||
{
|
||||
new() { Value = "Alarm1", Time = DateTime.UtcNow}
|
||||
};
|
||||
var observations = new List<PatientObservation>
|
||||
{
|
||||
new() { Value = "Alarm1", Time = DateTime.MinValue}
|
||||
};
|
||||
|
||||
_configObservationServiceMock.Setup(o => o.Map(It.IsAny<PatientObservationAlarm>(), It.IsAny<bool>()))
|
||||
.ReturnsAsync((PatientObservationAlarm obs, bool _) => obs); // Correct setup
|
||||
|
||||
_calculatedObservationsServiceMock.Setup(o => o.Map(It.IsAny<PatientObservationAlarm>(), It.IsAny<bool>()))
|
||||
.ReturnsAsync((PatientObservationAlarm obs, bool _) => obs); // Correct setup
|
||||
|
||||
// Act
|
||||
await _alarmService.ProcessAlarmObservations(alarmObservations, observations, patient, DateTime.UtcNow);
|
||||
|
||||
// Assert
|
||||
_alarmRepositoryMock.Verify(a => a.InsertOneAsync(It.IsAny<PatientObservationAlarm>()), Times.Once);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that when checking observation alarms for a patient observation with an "Event_PEEP_Low" configuration
|
||||
/// (coding system "ADAS_EVENT", description "EVT_LO and EVT_EXTR_LO"), the alarm service does not insert a new observation,
|
||||
/// as indicated by the verification that <c>InsertObservation</c> is never invoked.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task CheckObservationAlarm_Alarm_EventPEEP_PEEP_bajo_create_Event()
|
||||
{
|
||||
var obs = new PatientObservation();
|
||||
|
||||
var configs = new ConfigObservation
|
||||
public async Task CheckObservationAlarm_Alarm_EventPEEP_PEEP_bajo_create_Event()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Name = "Event_PEEP_Low",
|
||||
CodingSystem = "ADAS_EVENT",
|
||||
Description = "EVT_LO and EVT_EXTR_LO"
|
||||
};
|
||||
|
||||
_configObservationServiceMock.Setup(c => c.Get(It.IsAny<PatientObservation>(), false))
|
||||
.ReturnsAsync(configs);
|
||||
|
||||
await _alarmService.CheckObservationAlarm(obs);
|
||||
|
||||
|
||||
_observationServiceMock.Verify(o => o.InsertObservation(obs, true, true), Times.Never);
|
||||
}
|
||||
var obs = new PatientObservation();
|
||||
|
||||
var configs = new ConfigObservation
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Name = "Event_PEEP_Low",
|
||||
CodingSystem = "ADAS_EVENT",
|
||||
Description = "EVT_LO and EVT_EXTR_LO"
|
||||
};
|
||||
|
||||
_configObservationServiceMock.Setup(c => c.Get(It.IsAny<PatientObservation>(), false))
|
||||
.ReturnsAsync(configs);
|
||||
|
||||
await _alarmService.CheckObservationAlarm(obs);
|
||||
|
||||
|
||||
_observationServiceMock.Verify(o => o.InsertObservation(obs, true, true), Times.Never);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="AlarmService.CheckObservationAlarm"/> processes a patient observation
|
||||
/// matching a configured rule (name "EVT_LO" with required value "PEEP") by inserting a new
|
||||
/// observation with the original value preserved (e.g., "PEEP High") while the alarm
|
||||
/// configuration handles the red beacon signaling.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task CheckObservationAlarm_Should_Launch_Red_Alarm_And_Set_BeaconColor_Red()
|
||||
{
|
||||
var alarmConfig = new AlarmConfig
|
||||
public async Task CheckObservationAlarm_Should_Launch_Red_Alarm_And_Set_BeaconColor_Red()
|
||||
{
|
||||
Enabled = true,
|
||||
Priority = 10,
|
||||
Beacon = new AlarmItem
|
||||
var alarmConfig = new AlarmConfig
|
||||
{
|
||||
Enabled = true,
|
||||
BeaconColor = AlarmEnum.BeaconColor.Red, // Using the enum value
|
||||
EndAfter = 60 // Assuming the alarm should end after 60 seconds
|
||||
}
|
||||
};
|
||||
|
||||
var configs = new ConfigObservation
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Name = "Event_PEEP_Low",
|
||||
CodingSystem = "ADAS_EVENT",
|
||||
Description = "logs an event. No generate an alarm.",
|
||||
Alarm = alarmConfig,
|
||||
RequiredValue = "PEEP"
|
||||
};
|
||||
|
||||
var obsConfig = new ConfigObservation
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Name = "EVT_LO",
|
||||
CheckObservations = true,
|
||||
CreateObservation = [configs]
|
||||
};
|
||||
var patId = ObjectId.GenerateNewId();
|
||||
// Arrange
|
||||
var obs = new PatientObservation
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Name = "EVT_LO",
|
||||
PatientId = patId,
|
||||
Value = "PEEP High",
|
||||
Time = DateTime.UtcNow,
|
||||
CheckObservations = true,
|
||||
CreateObservation = [configs]
|
||||
};
|
||||
|
||||
_configObservationServiceMock.Setup(c => c.Get(It.IsAny<PatientObservation>(), false))
|
||||
.ReturnsAsync(obsConfig);
|
||||
|
||||
|
||||
// Act
|
||||
await _alarmService.CheckObservationAlarm(obs);
|
||||
|
||||
_observationServiceMock.Verify(
|
||||
o => o.InsertObservation(
|
||||
It.Is<PatientObservation>(ob => ob.Value.ToString() == "PEEP High"), true, true),
|
||||
Times.Once);
|
||||
}
|
||||
Priority = 10,
|
||||
Beacon = new AlarmItem
|
||||
{
|
||||
Enabled = true,
|
||||
BeaconColor = AlarmEnum.BeaconColor.Red, // Using the enum value
|
||||
EndAfter = 60 // Assuming the alarm should end after 60 seconds
|
||||
}
|
||||
};
|
||||
|
||||
var configs = new ConfigObservation
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Name = "Event_PEEP_Low",
|
||||
CodingSystem = "ADAS_EVENT",
|
||||
Description = "logs an event. No generate an alarm.",
|
||||
Alarm = alarmConfig,
|
||||
RequiredValue = "PEEP"
|
||||
};
|
||||
|
||||
var obsConfig = new ConfigObservation
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Name = "EVT_LO",
|
||||
CheckObservations = true,
|
||||
CreateObservation = [configs]
|
||||
};
|
||||
var patId = ObjectId.GenerateNewId();
|
||||
// Arrange
|
||||
var obs = new PatientObservation
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Name = "EVT_LO",
|
||||
PatientId = patId,
|
||||
Value = "PEEP High",
|
||||
Time = DateTime.UtcNow,
|
||||
CheckObservations = true,
|
||||
CreateObservation = [configs]
|
||||
};
|
||||
|
||||
_configObservationServiceMock.Setup(c => c.Get(It.IsAny<PatientObservation>(), false))
|
||||
.ReturnsAsync(obsConfig);
|
||||
|
||||
|
||||
// Act
|
||||
await _alarmService.CheckObservationAlarm(obs);
|
||||
|
||||
_observationServiceMock.Verify(
|
||||
o => o.InsertObservation(
|
||||
It.Is<PatientObservation>(ob => ob.Value.ToString() == "PEEP High"), true, true),
|
||||
Times.Once);
|
||||
}
|
||||
}
|
||||
@@ -14,12 +14,32 @@ namespace adas_core.Test.Services;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Provides a fake implementation of the <see cref="ILockProvider"/> interface, typically used as a test double or non-functional placeholder.
|
||||
/// </summary>
|
||||
public class FakeLockProvider : ILockProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Asynchronously attempts to acquire a resource identified by the specified key within the given timeout.
|
||||
/// This implementation always reports a successful acquisition by returning <c>true</c>.
|
||||
/// </summary>
|
||||
/// <param name="key">The identifier of the resource to acquire.</param>
|
||||
/// <param name="timeout">The maximum time to wait for the resource to become available.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> that always completes with <c>true</c>, indicating the resource was acquired.</returns>
|
||||
public Task<bool> AcquireAsync(string key, TimeSpan timeout) => Task.FromResult(true);
|
||||
/// <summary>
|
||||
/// Releases the resource associated with the specified key. This implementation completes immediately without performing any additional operation.
|
||||
/// </summary>
|
||||
/// <param name="key">The identifier of the resource to release.</param>
|
||||
public Task ReleaseAsync(string key) => Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a fake implementation of <see cref="LockManagerService"/>, typically used as a test double to provide controlled or simplified behavior in unit tests.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Inherits all members from <see cref="LockManagerService"/> and is intended to be used in place of the real service when actual locking functionality is not required.
|
||||
/// </remarks>
|
||||
public class FakeLockManagerService : LockManagerService
|
||||
{
|
||||
public FakeLockManagerService() : base(
|
||||
@@ -30,6 +50,12 @@ public class FakeLockManagerService : LockManagerService
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a fake or test double implementation of <see cref="RedisService"/> that also implements <see cref="ICacheService"/>, typically used to simulate Redis caching behavior in testing scenarios.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class combines the inheritance of <see cref="RedisService"/> with the contract of <see cref="ICacheService"/>, allowing it to stand in for a real Redis-backed cache during unit tests or development.
|
||||
/// </remarks>
|
||||
public class FakeRedisService : RedisService, ICacheService
|
||||
{
|
||||
public bool WasCalled { get; private set; }
|
||||
@@ -43,30 +69,55 @@ public class FakeRedisService : RedisService, ICacheService
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a cached object associated with the specified key, or creates and stores one using the provided factory if no cached entry exists.
|
||||
/// This implementation bypasses caching and directly invokes the factory, recording the invocation for verification purposes while ignoring the TTL and cancellation token.
|
||||
/// </summary>
|
||||
/// <param name="key">The cache key used to identify the stored object.</param>
|
||||
/// <param name="factory">A delegate that asynchronously produces the object to cache when no entry exists for the specified key.</param>
|
||||
/// <param name="ttl">An optional time-to-live duration for the cached entry. Not used in this implementation.</param>
|
||||
/// <param name="cancellationToken">A token to observe for cancellation requests. Not used in this implementation.</param>
|
||||
/// <returns>A task that represents the asynchronous operation, containing the object produced by the factory.</returns>
|
||||
Task<T> ICacheService.GetOrSetObjectAsync<T>(
|
||||
string key,
|
||||
Func<Task<T>> factory,
|
||||
TimeSpan? ttl,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
WasCalled = true;
|
||||
LastKey = key;
|
||||
return factory();
|
||||
}
|
||||
string key,
|
||||
Func<Task<T>> factory,
|
||||
TimeSpan? ttl,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
WasCalled = true;
|
||||
LastKey = key;
|
||||
return factory();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves or sets a cached object associated with the specified grouped field and patient identifier.
|
||||
/// Marks the call as executed via the <c>WasCalled</c> flag and returns the value produced by the supplied factory delegate.
|
||||
/// </summary>
|
||||
/// <param name="groupedField">The grouped field used to identify the cached object.</param>
|
||||
/// <param name="patientId">The identifier of the patient associated with the cached object.</param>
|
||||
/// <param name="factory">The asynchronous factory delegate invoked to produce the value when no cached entry exists.</param>
|
||||
/// <param name="ttl">An optional time-to-live duration for the cached entry.</param>
|
||||
/// <param name="cancellationToken">The token used to cancel the asynchronous operation.</param>
|
||||
/// <returns>The value of type <typeparamref name="T"/> produced by the <paramref name="factory"/> delegate.</returns>
|
||||
Task<T> ICacheService.GetOrSetObjectAsync<T>(
|
||||
GroupedField groupedField,
|
||||
ObjectId patientId,
|
||||
Func<Task<T>> factory,
|
||||
TimeSpan? ttl,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
WasCalled = true;
|
||||
return factory();
|
||||
}
|
||||
GroupedField groupedField,
|
||||
ObjectId patientId,
|
||||
Func<Task<T>> factory,
|
||||
TimeSpan? ttl,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
WasCalled = true;
|
||||
return factory();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a fake implementation of <see cref="CacheService"/> that also implements the <see cref="ICacheService"/> interface, typically used for testing or stubbing scenarios.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class combines inheritance from the concrete <see cref="CacheService"/> base class with the <see cref="ICacheService"/> contract, allowing it to be used wherever an <see cref="ICacheService"/> is required.
|
||||
/// </remarks>
|
||||
public class FakeCacheService : CacheService, ICacheService
|
||||
{
|
||||
public bool WasCalled { get; private set; }
|
||||
@@ -100,6 +151,12 @@ public class FakeCacheService : CacheService, ICacheService
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a fake implementation of the cache service, used for testing or scenarios where a no-op cache behavior is required.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class inherits from <see cref="NoCacheService"/> and implements the <see cref="ICacheService"/> interface, providing a non-functional cache suitable for unit tests or environments where caching should be bypassed.
|
||||
/// </remarks>
|
||||
public class FakeNoCacheService : NoCacheService, ICacheService
|
||||
{
|
||||
public bool WasCalled { get; private set; }
|
||||
@@ -138,21 +195,24 @@ public class CacheDispatcherTest
|
||||
private CacheSettings _cacheSettings = null!;
|
||||
private CacheDispatcher _cacheDispatcher = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the test environment by instantiating fake implementations of the Redis, in-memory, and no-op cache services, along with default <see cref="CacheSettings"/>, and constructs a <see cref="CacheDispatcher"/> under test using these dependencies.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_redisServiceFake = new FakeRedisService();
|
||||
_memoryServiceFake = new FakeCacheService();
|
||||
_noopServiceFake = new FakeNoCacheService();
|
||||
|
||||
_cacheSettings = new CacheSettings();
|
||||
|
||||
_cacheDispatcher = new CacheDispatcher(
|
||||
_redisServiceFake,
|
||||
_memoryServiceFake,
|
||||
_noopServiceFake,
|
||||
_cacheSettings);
|
||||
}
|
||||
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
|
||||
|
||||
@@ -240,17 +300,20 @@ public class CacheDispatcherTest
|
||||
Assert.That(_noopServiceFake.WasCalled, Is.False, "NoCacheService NO debería haber sido invocado");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="CacheKeyClassifier.Classify"/> returns <see cref="CacheEnum.EntityType.Unknown"/> when the provided cache key does not start with any recognized prefix.
|
||||
/// </summary>
|
||||
[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));
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
@@ -7,15 +7,19 @@ public class CacheServiceTest
|
||||
{
|
||||
private CacheService _svc = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the test environment by creating a <see cref="LockManagerService"/> with a mock logger
|
||||
/// and an in-memory lock provider, and instantiating the <see cref="CacheService"/> under test with that lock manager.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
var lockMgr = new LockManagerService(
|
||||
new Mock<ILogger<LockManagerService>>().Object,
|
||||
new InMemoryLockProvider());
|
||||
|
||||
_svc = new CacheService(lockMgr);
|
||||
}
|
||||
public void SetUp()
|
||||
{
|
||||
var lockMgr = new LockManagerService(
|
||||
new Mock<ILogger<LockManagerService>>().Object,
|
||||
new InMemoryLockProvider());
|
||||
|
||||
_svc = new CacheService(lockMgr);
|
||||
}
|
||||
#region TC-31
|
||||
[Test]
|
||||
public async Task GetOrSetObjectAsync_ReturnsCachedValue_AndDoesNotInvokeFactory_WhenKeyAlreadyExists()
|
||||
@@ -37,172 +41,193 @@ public class CacheServiceTest
|
||||
}
|
||||
#endregion
|
||||
#region TC-32
|
||||
/// <summary>
|
||||
/// Verifies that <c>GetOrSetObjectAsync</c> invokes the supplied factory on the first call, persists the produced value, and on subsequent calls returns the cached value without invoking the factory again.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetOrSetObjectAsync_InvokesFactory_StoresResult_AndDoesNotInvokeAgainOnSecondCall()
|
||||
{
|
||||
const string key = "patients:latestObs:new";
|
||||
const string factoryValue = "factory-result";
|
||||
var factoryCallCount = 0;
|
||||
|
||||
var firstResult = await _svc.GetOrSetObjectAsync(key, () =>
|
||||
public async Task GetOrSetObjectAsync_InvokesFactory_StoresResult_AndDoesNotInvokeAgainOnSecondCall()
|
||||
{
|
||||
factoryCallCount++;
|
||||
return Task.FromResult(factoryValue);
|
||||
});
|
||||
|
||||
Assert.That(factoryCallCount, Is.EqualTo(1));
|
||||
Assert.That(firstResult, Is.EqualTo(factoryValue));
|
||||
|
||||
var cached = await _svc.GetObjectAsync<string>(key);
|
||||
Assert.That(cached, Is.EqualTo(factoryValue));
|
||||
|
||||
var secondResult = await _svc.GetOrSetObjectAsync(key, () =>
|
||||
{
|
||||
factoryCallCount++;
|
||||
return Task.FromResult("second-call-value");
|
||||
});
|
||||
|
||||
Assert.That(factoryCallCount, Is.EqualTo(1));
|
||||
Assert.That(secondResult, Is.EqualTo(factoryValue));
|
||||
}
|
||||
const string key = "patients:latestObs:new";
|
||||
const string factoryValue = "factory-result";
|
||||
var factoryCallCount = 0;
|
||||
|
||||
var firstResult = await _svc.GetOrSetObjectAsync(key, () =>
|
||||
{
|
||||
factoryCallCount++;
|
||||
return Task.FromResult(factoryValue);
|
||||
});
|
||||
|
||||
Assert.That(factoryCallCount, Is.EqualTo(1));
|
||||
Assert.That(firstResult, Is.EqualTo(factoryValue));
|
||||
|
||||
var cached = await _svc.GetObjectAsync<string>(key);
|
||||
Assert.That(cached, Is.EqualTo(factoryValue));
|
||||
|
||||
var secondResult = await _svc.GetOrSetObjectAsync(key, () =>
|
||||
{
|
||||
factoryCallCount++;
|
||||
return Task.FromResult("second-call-value");
|
||||
});
|
||||
|
||||
Assert.That(factoryCallCount, Is.EqualTo(1));
|
||||
Assert.That(secondResult, Is.EqualTo(factoryValue));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TC-33
|
||||
/// <summary>
|
||||
/// Verifies that <c>GetOrSetObjectAsync</c> does not cache <see langword="null"/> results, ensuring the factory delegate is re-invoked on subsequent calls for the same key when the previously produced value was <see langword="null"/>.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetOrSetObjectAsync_DoesNotCacheNullResult_AndInvokesFactoryOnSubsequentCalls()
|
||||
{
|
||||
const string key = "patients:latestObs:null";
|
||||
var factoryCallCount = 0;
|
||||
|
||||
await _svc.GetOrSetObjectAsync(key, () =>
|
||||
public async Task GetOrSetObjectAsync_DoesNotCacheNullResult_AndInvokesFactoryOnSubsequentCalls()
|
||||
{
|
||||
factoryCallCount++;
|
||||
return Task.FromResult<string?>(null);
|
||||
});
|
||||
|
||||
Assert.That(factoryCallCount, Is.EqualTo(1));
|
||||
|
||||
await _svc.GetOrSetObjectAsync(key, () =>
|
||||
{
|
||||
factoryCallCount++;
|
||||
return Task.FromResult<string?>(null);
|
||||
});
|
||||
|
||||
Assert.That(factoryCallCount, Is.EqualTo(2));
|
||||
}
|
||||
const string key = "patients:latestObs:null";
|
||||
var factoryCallCount = 0;
|
||||
|
||||
await _svc.GetOrSetObjectAsync(key, () =>
|
||||
{
|
||||
factoryCallCount++;
|
||||
return Task.FromResult<string?>(null);
|
||||
});
|
||||
|
||||
Assert.That(factoryCallCount, Is.EqualTo(1));
|
||||
|
||||
await _svc.GetOrSetObjectAsync(key, () =>
|
||||
{
|
||||
factoryCallCount++;
|
||||
return Task.FromResult<string?>(null);
|
||||
});
|
||||
|
||||
Assert.That(factoryCallCount, Is.EqualTo(2));
|
||||
}
|
||||
#endregion
|
||||
#region TC-34
|
||||
/// <summary>
|
||||
/// Verifies that when two threads call <c>GetOrSetObjectAsync</c> concurrently for the same key,
|
||||
/// the second thread does not invoke its factory if the first thread has already inserted the value,
|
||||
/// and both threads receive the value produced by the first thread's factory.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetOrSetObjectAsync_SecondCheckInLock_PreventsFactoryExecution_WhenValueAlreadyInsertedByFirstThread()
|
||||
{
|
||||
const string key = "patients:concurrent:abc";
|
||||
var factoryCallCount = 0;
|
||||
var task1InFactory = new SemaphoreSlim(0, 1);
|
||||
var task1CanFinish = new SemaphoreSlim(0, 1);
|
||||
|
||||
async Task<string> ControlledFactory()
|
||||
public async Task GetOrSetObjectAsync_SecondCheckInLock_PreventsFactoryExecution_WhenValueAlreadyInsertedByFirstThread()
|
||||
{
|
||||
Interlocked.Increment(ref factoryCallCount);
|
||||
task1InFactory.Release();
|
||||
await task1CanFinish.WaitAsync();
|
||||
return "first-result";
|
||||
const string key = "patients:concurrent:abc";
|
||||
var factoryCallCount = 0;
|
||||
var task1InFactory = new SemaphoreSlim(0, 1);
|
||||
var task1CanFinish = new SemaphoreSlim(0, 1);
|
||||
|
||||
async Task<string> ControlledFactory()
|
||||
{
|
||||
Interlocked.Increment(ref factoryCallCount);
|
||||
task1InFactory.Release();
|
||||
await task1CanFinish.WaitAsync();
|
||||
return "first-result";
|
||||
}
|
||||
|
||||
var t1 = _svc.GetOrSetObjectAsync(key, ControlledFactory);
|
||||
|
||||
await task1InFactory.WaitAsync();
|
||||
|
||||
var t2 = _svc.GetOrSetObjectAsync(key, () =>
|
||||
{
|
||||
Interlocked.Increment(ref factoryCallCount);
|
||||
return Task.FromResult("second-result");
|
||||
});
|
||||
|
||||
await Task.Delay(20);
|
||||
|
||||
task1CanFinish.Release();
|
||||
|
||||
var r1 = await t1;
|
||||
var r2 = await t2;
|
||||
|
||||
Assert.That(factoryCallCount, Is.EqualTo(1));
|
||||
Assert.That(r1, Is.EqualTo("first-result"));
|
||||
Assert.That(r2, Is.EqualTo("first-result"));
|
||||
}
|
||||
|
||||
var t1 = _svc.GetOrSetObjectAsync(key, ControlledFactory);
|
||||
|
||||
await task1InFactory.WaitAsync();
|
||||
|
||||
var t2 = _svc.GetOrSetObjectAsync(key, () =>
|
||||
{
|
||||
Interlocked.Increment(ref factoryCallCount);
|
||||
return Task.FromResult("second-result");
|
||||
});
|
||||
|
||||
await Task.Delay(20);
|
||||
|
||||
task1CanFinish.Release();
|
||||
|
||||
var r1 = await t1;
|
||||
var r2 = await t2;
|
||||
|
||||
Assert.That(factoryCallCount, Is.EqualTo(1));
|
||||
Assert.That(r1, Is.EqualTo("first-result"));
|
||||
Assert.That(r2, Is.EqualTo("first-result"));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TC-35
|
||||
/// <summary>
|
||||
/// Verifies that calling <c>DeleteObjectAsync</c> removes the stored value for the given key, and that the next call to <c>GetOrSetObjectAsync</c> invokes the factory delegate to produce a new value instead of returning a previously cached one.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task DeleteObjectAsync_RemovesKey_AndFactoryIsInvokedOnNextCall()
|
||||
{
|
||||
const string key = "patients:latestObs:delete";
|
||||
await _svc.SetObjectAsync(key, "stored-value");
|
||||
|
||||
await _svc.DeleteObjectAsync(key);
|
||||
|
||||
var valueAfterDelete = await _svc.GetObjectAsync<string>(key);
|
||||
Assert.That(valueAfterDelete, Is.Null);
|
||||
|
||||
var factoryCallCount = 0;
|
||||
var result = await _svc.GetOrSetObjectAsync(key, () =>
|
||||
public async Task DeleteObjectAsync_RemovesKey_AndFactoryIsInvokedOnNextCall()
|
||||
{
|
||||
factoryCallCount++;
|
||||
return Task.FromResult("after-delete");
|
||||
});
|
||||
|
||||
Assert.That(factoryCallCount, Is.EqualTo(1));
|
||||
Assert.That(result, Is.EqualTo("after-delete"));
|
||||
}
|
||||
const string key = "patients:latestObs:delete";
|
||||
await _svc.SetObjectAsync(key, "stored-value");
|
||||
|
||||
await _svc.DeleteObjectAsync(key);
|
||||
|
||||
var valueAfterDelete = await _svc.GetObjectAsync<string>(key);
|
||||
Assert.That(valueAfterDelete, Is.Null);
|
||||
|
||||
var factoryCallCount = 0;
|
||||
var result = await _svc.GetOrSetObjectAsync(key, () =>
|
||||
{
|
||||
factoryCallCount++;
|
||||
return Task.FromResult("after-delete");
|
||||
});
|
||||
|
||||
Assert.That(factoryCallCount, Is.EqualTo(1));
|
||||
Assert.That(result, Is.EqualTo("after-delete"));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TC-36
|
||||
/// <summary>
|
||||
/// Verifies that <c>DeleteByPatternAsync</c> removes only the cache entries whose keys match the supplied pattern while preserving unrelated keys that do not match.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task DeleteByPatternAsync_RemovesMatchingKeys_AndKeepsNonMatchingKeys()
|
||||
{
|
||||
await _svc.SetObjectAsync("patients:abc", "val1");
|
||||
await _svc.SetObjectAsync("patients:def", "val2");
|
||||
await _svc.SetObjectAsync("appointments:xyz", "val3");
|
||||
|
||||
var deleted = await _svc.DeleteByPatternAsync("patients:");
|
||||
|
||||
Assert.That(deleted, Is.EqualTo(2));
|
||||
|
||||
var p1 = await _svc.GetObjectAsync<string>("patients:abc");
|
||||
var p2 = await _svc.GetObjectAsync<string>("patients:def");
|
||||
var a1 = await _svc.GetObjectAsync<string>("appointments:xyz");
|
||||
|
||||
Assert.That(p1, Is.Null);
|
||||
Assert.That(p2, Is.Null);
|
||||
Assert.That(a1, Is.EqualTo("val3"));
|
||||
}
|
||||
public async Task DeleteByPatternAsync_RemovesMatchingKeys_AndKeepsNonMatchingKeys()
|
||||
{
|
||||
await _svc.SetObjectAsync("patients:abc", "val1");
|
||||
await _svc.SetObjectAsync("patients:def", "val2");
|
||||
await _svc.SetObjectAsync("appointments:xyz", "val3");
|
||||
|
||||
var deleted = await _svc.DeleteByPatternAsync("patients:");
|
||||
|
||||
Assert.That(deleted, Is.EqualTo(2));
|
||||
|
||||
var p1 = await _svc.GetObjectAsync<string>("patients:abc");
|
||||
var p2 = await _svc.GetObjectAsync<string>("patients:def");
|
||||
var a1 = await _svc.GetObjectAsync<string>("appointments:xyz");
|
||||
|
||||
Assert.That(p1, Is.Null);
|
||||
Assert.That(p2, Is.Null);
|
||||
Assert.That(a1, Is.EqualTo("val3"));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TC-37
|
||||
/// <summary>
|
||||
/// Verifies that <c>CleanCache</c> removes all entries from the cache, causing subsequent
|
||||
/// <c>GetOrSetObjectAsync</c> calls to invoke the provided factory delegate to repopulate the value.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task CleanCache_RemovesAllKeys_AndFactoryIsInvokedAfterClean()
|
||||
{
|
||||
await _svc.SetObjectAsync("patients:1", "v1");
|
||||
await _svc.SetObjectAsync("patients:2", "v2");
|
||||
await _svc.SetObjectAsync("appointments:1", "v3");
|
||||
await _svc.SetObjectAsync("configDisplays:1", "v4");
|
||||
await _svc.SetObjectAsync("pumpObs:1", "v5");
|
||||
|
||||
_svc.CleanCache();
|
||||
|
||||
Assert.That(await _svc.GetObjectAsync<string>("patients:1"), Is.Null);
|
||||
Assert.That(await _svc.GetObjectAsync<string>("patients:2"), Is.Null);
|
||||
Assert.That(await _svc.GetObjectAsync<string>("appointments:1"), Is.Null);
|
||||
Assert.That(await _svc.GetObjectAsync<string>("configDisplays:1"), Is.Null);
|
||||
Assert.That(await _svc.GetObjectAsync<string>("pumpObs:1"), Is.Null);
|
||||
|
||||
var factoryCallCount = 0;
|
||||
await _svc.GetOrSetObjectAsync("patients:1", () =>
|
||||
public async Task CleanCache_RemovesAllKeys_AndFactoryIsInvokedAfterClean()
|
||||
{
|
||||
factoryCallCount++;
|
||||
return Task.FromResult("after-clean");
|
||||
});
|
||||
|
||||
Assert.That(factoryCallCount, Is.EqualTo(1));
|
||||
}
|
||||
await _svc.SetObjectAsync("patients:1", "v1");
|
||||
await _svc.SetObjectAsync("patients:2", "v2");
|
||||
await _svc.SetObjectAsync("appointments:1", "v3");
|
||||
await _svc.SetObjectAsync("configDisplays:1", "v4");
|
||||
await _svc.SetObjectAsync("pumpObs:1", "v5");
|
||||
|
||||
_svc.CleanCache();
|
||||
|
||||
Assert.That(await _svc.GetObjectAsync<string>("patients:1"), Is.Null);
|
||||
Assert.That(await _svc.GetObjectAsync<string>("patients:2"), Is.Null);
|
||||
Assert.That(await _svc.GetObjectAsync<string>("appointments:1"), Is.Null);
|
||||
Assert.That(await _svc.GetObjectAsync<string>("configDisplays:1"), Is.Null);
|
||||
Assert.That(await _svc.GetObjectAsync<string>("pumpObs:1"), Is.Null);
|
||||
|
||||
var factoryCallCount = 0;
|
||||
await _svc.GetOrSetObjectAsync("patients:1", () =>
|
||||
{
|
||||
factoryCallCount++;
|
||||
return Task.FromResult("after-clean");
|
||||
});
|
||||
|
||||
Assert.That(factoryCallCount, Is.EqualTo(1));
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
@@ -11,49 +11,55 @@ internal class CameraServiceTest
|
||||
//Dictionary<string, object> cameraSettings;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// NUnit <see cref="SetUpAttribute"/> method executed before each test to initialize shared test state, such as camera configuration dictionaries, mocked camera and logger services, and a mocked subscribers service. Currently all initialization logic is commented out, so the method performs no setup actions.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
//cameraSettings = new Dictionary<string, object>()
|
||||
//{
|
||||
// { "camHost", "http://localhost:8080" },
|
||||
// { "camUser", "username" },
|
||||
// { "camPassword", "password" }
|
||||
//};
|
||||
//cameraServiceMock = new Mock<CameraService>();
|
||||
|
||||
//logger = new Mock<ILogger<CameraService>>();
|
||||
|
||||
//cameraService = new CameraService(
|
||||
// logger.Object
|
||||
// );
|
||||
|
||||
|
||||
// Create a mock of the singleton class subscribers
|
||||
//var mockSingleton = new Mock<ISubscribersService>();
|
||||
|
||||
//var subscribers = new List<WsSubscriber>();
|
||||
|
||||
// Set up the mock object to return a specific value when a method is called
|
||||
//mockSingleton.Setup(x => x.GetSubscribers()).Returns(subscribers);
|
||||
}
|
||||
public void Setup()
|
||||
{
|
||||
//cameraSettings = new Dictionary<string, object>()
|
||||
//{
|
||||
// { "camHost", "http://localhost:8080" },
|
||||
// { "camUser", "username" },
|
||||
// { "camPassword", "password" }
|
||||
//};
|
||||
//cameraServiceMock = new Mock<CameraService>();
|
||||
|
||||
//logger = new Mock<ILogger<CameraService>>();
|
||||
|
||||
//cameraService = new CameraService(
|
||||
// logger.Object
|
||||
// );
|
||||
|
||||
|
||||
// Create a mock of the singleton class subscribers
|
||||
//var mockSingleton = new Mock<ISubscribersService>();
|
||||
|
||||
//var subscribers = new List<WsSubscriber>();
|
||||
|
||||
// Set up the mock object to return a specific value when a method is called
|
||||
//mockSingleton.Setup(x => x.GetSubscribers()).Returns(subscribers);
|
||||
}
|
||||
|
||||
//TODO HttpWebResponse test
|
||||
//[Test]
|
||||
/// <summary>
|
||||
/// Verifies that the <c>MaskStream</c> operation on the camera service returns a valid response when invoked with activation and coordinate parameters against the configured camera settings. Covers the scenario where the underlying grab response is null, ensuring the service still produces a non-null response with the expected status code and content.
|
||||
/// </summary>
|
||||
public void MaskStream_Return_Ok()
|
||||
{
|
||||
//bool activate = true;
|
||||
//string coordinates = "100,100";
|
||||
//var expectedResponse = new HttpResponseMessage();
|
||||
|
||||
////cameraServiceMock.Setup(c => c.GrabResponse(It.IsAny<string>(), It.IsAny<string>())).Returns(((string)null));
|
||||
|
||||
//// Act
|
||||
//var response = cameraService.MaskStream(activate, coordinates, cameraSettings);
|
||||
|
||||
//// Assert
|
||||
//Assert.IsNotNull(response);
|
||||
//Assert.AreEqual(expectedResponse.StatusCode, response.StatusCode);
|
||||
//Assert.AreEqual(expectedResponse.Content, response.Content);
|
||||
}
|
||||
{
|
||||
//bool activate = true;
|
||||
//string coordinates = "100,100";
|
||||
//var expectedResponse = new HttpResponseMessage();
|
||||
|
||||
////cameraServiceMock.Setup(c => c.GrabResponse(It.IsAny<string>(), It.IsAny<string>())).Returns(((string)null));
|
||||
|
||||
//// Act
|
||||
//var response = cameraService.MaskStream(activate, coordinates, cameraSettings);
|
||||
|
||||
//// Assert
|
||||
//Assert.IsNotNull(response);
|
||||
//Assert.AreEqual(expectedResponse.StatusCode, response.StatusCode);
|
||||
//Assert.AreEqual(expectedResponse.Content, response.Content);
|
||||
}
|
||||
}
|
||||
@@ -73,309 +73,373 @@ public class ConfigObservationServiceTest
|
||||
new() { Id = ObjectId.GenerateNewId(), Name = "Alarm_BlueCode", CodingSystem = "ADAS_EVENT" }
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the test fixture by creating mock instances of all dependencies required by <see cref="ConfigObservationService"/>,
|
||||
/// including the repository, unit service, audit service, HTTP context accessor, cache service, and logger.
|
||||
/// Configures a default authenticated <see cref="ClaimsPrincipal"/> in the HTTP context and sets the cache mocks to bypass caching by executing the factory function directly,
|
||||
/// ensuring repository calls are invoked during tests.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_repo = new Mock<IConfigObservationRepository>();
|
||||
_unitSvc = new Mock<IUnitService>();
|
||||
_auditSvc = new Mock<ILocalAuditService>();
|
||||
_http = new Mock<IHttpContextAccessor>();
|
||||
_cache = new Mock<ICacheService>();
|
||||
_logger = new Mock<ILogger<ConfigObservationService>>();
|
||||
|
||||
var user = new ClaimsPrincipal(
|
||||
new ClaimsIdentity([new Claim(ClaimTypes.Name, "TestUser")], "mock"));
|
||||
|
||||
_http.Setup(x => x.HttpContext).Returns(new DefaultHttpContext { User = user });
|
||||
|
||||
_settings = Options.Create(new ApiSettings
|
||||
public void Setup()
|
||||
{
|
||||
ConfigObservation = new ConfigObservationSettings
|
||||
_repo = new Mock<IConfigObservationRepository>();
|
||||
_unitSvc = new Mock<IUnitService>();
|
||||
_auditSvc = new Mock<ILocalAuditService>();
|
||||
_http = new Mock<IHttpContextAccessor>();
|
||||
_cache = new Mock<ICacheService>();
|
||||
_logger = new Mock<ILogger<ConfigObservationService>>();
|
||||
|
||||
var user = new ClaimsPrincipal(
|
||||
new ClaimsIdentity([new Claim(ClaimTypes.Name, "TestUser")], "mock"));
|
||||
|
||||
_http.Setup(x => x.HttpContext).Returns(new DefaultHttpContext { User = user });
|
||||
|
||||
_settings = Options.Create(new ApiSettings
|
||||
{
|
||||
IgnoreUnknownObservation = false,
|
||||
Refresh = null
|
||||
},
|
||||
});
|
||||
|
||||
_cacheSettings = Options.Create(new CacheSettings());
|
||||
|
||||
// KEY: mock cache to execute repository calls
|
||||
_cache.Setup(c => c.GetOrSetObjectAsync(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<Func<Task<ICollection<ConfigObservation>>>>(),
|
||||
It.IsAny<TimeSpan?>(),
|
||||
It.IsAny<CancellationToken>()))
|
||||
.Returns((string _, Func<Task<ICollection<ConfigObservation>>> f, TimeSpan? __, CancellationToken ___) => f());
|
||||
|
||||
_cache.Setup(c => c.GetOrSetObjectAsync(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<Func<Task<ConfigObservation>>>(),
|
||||
It.IsAny<TimeSpan?>(),
|
||||
It.IsAny<CancellationToken>()))
|
||||
.Returns((string _, Func<Task<ConfigObservation>> f, TimeSpan? __, CancellationToken ___) => f());
|
||||
|
||||
_service = new ConfigObservationService(
|
||||
_repo.Object,
|
||||
_settings,
|
||||
_cacheSettings,
|
||||
_logger.Object,
|
||||
_unitSvc.Object,
|
||||
_http.Object,
|
||||
_auditSvc.Object,
|
||||
_cache.Object);
|
||||
|
||||
_repo.Setup(x => x.FindAll()).ReturnsAsync([ConfigList]);
|
||||
}
|
||||
ConfigObservation = new ConfigObservationSettings
|
||||
{
|
||||
IgnoreUnknownObservation = false,
|
||||
Refresh = null
|
||||
},
|
||||
});
|
||||
|
||||
_cacheSettings = Options.Create(new CacheSettings());
|
||||
|
||||
// KEY: mock cache to execute repository calls
|
||||
_cache.Setup(c => c.GetOrSetObjectAsync(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<Func<Task<ICollection<ConfigObservation>>>>(),
|
||||
It.IsAny<TimeSpan?>(),
|
||||
It.IsAny<CancellationToken>()))
|
||||
.Returns((string _, Func<Task<ICollection<ConfigObservation>>> f, TimeSpan? __, CancellationToken ___) => f());
|
||||
|
||||
_cache.Setup(c => c.GetOrSetObjectAsync(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<Func<Task<ConfigObservation>>>(),
|
||||
It.IsAny<TimeSpan?>(),
|
||||
It.IsAny<CancellationToken>()))
|
||||
.Returns((string _, Func<Task<ConfigObservation>> f, TimeSpan? __, CancellationToken ___) => f());
|
||||
|
||||
_service = new ConfigObservationService(
|
||||
_repo.Object,
|
||||
_settings,
|
||||
_cacheSettings,
|
||||
_logger.Object,
|
||||
_unitSvc.Object,
|
||||
_http.Object,
|
||||
_auditSvc.Object,
|
||||
_cache.Object);
|
||||
|
||||
_repo.Setup(x => x.FindAll()).ReturnsAsync([ConfigList]);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// TESTS
|
||||
// ---------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that querying a patient observation by <c>CodingSystem</c> only, without specifying a code or name, returns a null result.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Get_config_observation_item_by_codingSystem_only_return_null()
|
||||
{
|
||||
var obs = new PatientObservation
|
||||
public async Task Get_config_observation_item_by_codingSystem_only_return_null()
|
||||
{
|
||||
CodingSystem = "ADAS_EVENT",
|
||||
Code = "Pump_X",
|
||||
Name = "Alarm_Pump_X"
|
||||
};
|
||||
|
||||
var result = await _service.Get(obs);
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Get_config_observation_item_by_code_and_codingSystem()
|
||||
{
|
||||
_repo.Setup(x => x.FindAll()).ReturnsAsync(_allConfigList);
|
||||
|
||||
var obs = new BasePatientObservation
|
||||
{
|
||||
Name = "Hemo^GBr",
|
||||
Code = "12345",
|
||||
CodingSystem = "SNM"
|
||||
};
|
||||
|
||||
var result = await _service.Get(obs);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result!.Name, Is.EqualTo("Hemoglobina"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Get_config_observation_item_by_name()
|
||||
{
|
||||
_repo.Setup(x => x.FindAll()).ReturnsAsync(_allConfigList);
|
||||
|
||||
var obs = new BasePatientObservation { Name = "Hemoglobina" };
|
||||
|
||||
var result = await _service.Get(obs);
|
||||
|
||||
Assert.That(result!.Name, Is.EqualTo("Hemoglobina"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Get_config_observation_item_by_name_not_exist_returns_null()
|
||||
{
|
||||
_repo.Setup(x => x.FindAll()).ReturnsAsync(_allConfigList);
|
||||
|
||||
var obs = new BasePatientObservation { Name = "XXX" };
|
||||
|
||||
var result = await _service.Get(obs);
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Get_config_by_code_and_parent()
|
||||
{
|
||||
_repo.Setup(x => x.FindAll()).ReturnsAsync(_allConfigList);
|
||||
|
||||
var obs = new BasePatientObservation
|
||||
{
|
||||
Code = "555",
|
||||
CodingSystem = "MG4",
|
||||
ParentData = new ParentDataClass
|
||||
var obs = new PatientObservation
|
||||
{
|
||||
Code = "3333",
|
||||
CodingSystem = "ADAS_EVENT",
|
||||
Code = "Pump_X",
|
||||
Name = "Alarm_Pump_X"
|
||||
};
|
||||
|
||||
var result = await _service.Get(obs);
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>Get</c> returns the matching patient observation configuration for a given observation identified by its code and coding system.
|
||||
/// Asserts that the resolved item is not null and that the displayed name is mapped from the configured lookup to the expected localized value.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Get_config_observation_item_by_code_and_codingSystem()
|
||||
{
|
||||
_repo.Setup(x => x.FindAll()).ReturnsAsync(_allConfigList);
|
||||
|
||||
var obs = new BasePatientObservation
|
||||
{
|
||||
Name = "Hemo^GBr",
|
||||
Code = "12345",
|
||||
CodingSystem = "SNM"
|
||||
}
|
||||
};
|
||||
|
||||
var result = await _service.Get(obs);
|
||||
|
||||
Assert.That(result!.Name, Is.EqualTo("ph"));
|
||||
}
|
||||
};
|
||||
|
||||
var result = await _service.Get(obs);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result!.Name, Is.EqualTo("Hemoglobina"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the service retrieves the correct configuration observation item by its name,
|
||||
/// matching the requested observation against the list returned by the repository and returning
|
||||
/// the item with the expected name.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Map_unknown_ignore_true_returns_null()
|
||||
{
|
||||
_settings.Value.ConfigObservation!.IgnoreUnknownObservation = true;
|
||||
_repo.Setup(x => x.FindAll()).ReturnsAsync([]);
|
||||
|
||||
var result = await _service.Map(new BasePatientObservation { Name = "XX" });
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Map_unknown_ignore_false_returns_obs()
|
||||
{
|
||||
_settings.Value.ConfigObservation!.IgnoreUnknownObservation = false;
|
||||
_repo.Setup(x => x.FindAll()).ReturnsAsync([]);
|
||||
|
||||
var obs = new BasePatientObservation { Name = "XX" };
|
||||
|
||||
var result = await _service.Map(obs);
|
||||
|
||||
Assert.That(result, Is.EqualTo(obs));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Map_threshold_Ok()
|
||||
{
|
||||
_repo.Setup(x => x.FindAll()).ReturnsAsync(_allConfigList);
|
||||
|
||||
var obs = new PatientObservation
|
||||
public async Task Get_config_observation_item_by_name()
|
||||
{
|
||||
Name = "SOFA",
|
||||
CodingSystem = "SNM",
|
||||
Value = 14
|
||||
};
|
||||
|
||||
var result = await _service.Map(obs);
|
||||
|
||||
Assert.That(result!.Status, Is.EqualTo(StatusEnum.Type.Ok));
|
||||
}
|
||||
_repo.Setup(x => x.FindAll()).ReturnsAsync(_allConfigList);
|
||||
|
||||
var obs = new BasePatientObservation { Name = "Hemoglobina" };
|
||||
|
||||
var result = await _service.Get(obs);
|
||||
|
||||
Assert.That(result!.Name, Is.EqualTo("Hemoglobina"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the service returns null when a patient observation item is requested by a name that does not exist in the configuration list.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Map_threshold_Warning()
|
||||
{
|
||||
_repo.Setup(x => x.FindAll()).ReturnsAsync(_allConfigList);
|
||||
|
||||
var obs = new PatientObservation
|
||||
public async Task Get_config_observation_item_by_name_not_exist_returns_null()
|
||||
{
|
||||
Name = "SOFA",
|
||||
CodingSystem = "SNM",
|
||||
Value = 13
|
||||
};
|
||||
|
||||
var result = await _service.Map(obs);
|
||||
|
||||
Assert.That(result!.Status, Is.EqualTo(StatusEnum.Type.Warning));
|
||||
}
|
||||
_repo.Setup(x => x.FindAll()).ReturnsAsync(_allConfigList);
|
||||
|
||||
var obs = new BasePatientObservation { Name = "XXX" };
|
||||
|
||||
var result = await _service.Get(obs);
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the service retrieves the correct configuration by matching both the observation code with its coding system and the parent data code with its coding system, returning the configuration named "ph".
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Map_threshold_Alert()
|
||||
{
|
||||
_repo.Setup(x => x.FindAll()).ReturnsAsync(_allConfigList);
|
||||
|
||||
var obs = new PatientObservation
|
||||
public async Task Get_config_by_code_and_parent()
|
||||
{
|
||||
Name = "SOFA",
|
||||
CodingSystem = "SNM",
|
||||
Value = 9
|
||||
};
|
||||
|
||||
var result = await _service.Map(obs);
|
||||
|
||||
Assert.That(result!.Status, Is.EqualTo(StatusEnum.Type.Alert));
|
||||
}
|
||||
_repo.Setup(x => x.FindAll()).ReturnsAsync(_allConfigList);
|
||||
|
||||
var obs = new BasePatientObservation
|
||||
{
|
||||
Code = "555",
|
||||
CodingSystem = "MG4",
|
||||
ParentData = new ParentDataClass
|
||||
{
|
||||
Code = "3333",
|
||||
CodingSystem = "SNM"
|
||||
}
|
||||
};
|
||||
|
||||
var result = await _service.Get(obs);
|
||||
|
||||
Assert.That(result!.Name, Is.EqualTo("ph"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the mapping service returns <c>null</c> when the observation name is unknown
|
||||
/// and the configuration is set to ignore unknown observations.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Map_parent_ok()
|
||||
{
|
||||
_repo.Setup(x => x.FindById(Id)).ReturnsAsync(ConfigList);
|
||||
|
||||
var fc = new PatientObservation
|
||||
public async Task Map_unknown_ignore_true_returns_null()
|
||||
{
|
||||
Id = Id,
|
||||
Name = "FC",
|
||||
Value = 70
|
||||
};
|
||||
|
||||
var result = await _service.Map(fc);
|
||||
|
||||
Assert.That(result!.Status, Is.EqualTo(StatusEnum.Type.Ok));
|
||||
}
|
||||
_settings.Value.ConfigObservation!.IgnoreUnknownObservation = true;
|
||||
_repo.Setup(x => x.FindAll()).ReturnsAsync([]);
|
||||
|
||||
var result = await _service.Map(new BasePatientObservation { Name = "XX" });
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that when ConfigObservation.IgnoreUnknownObservation is set to <c>false</c>,
|
||||
/// the <c>Map</c> method returns the original observation as-is when no matching record is found
|
||||
/// in the repository, rather than discarding it as an unknown observation.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task UpdateConfig_ok()
|
||||
{
|
||||
var newCfg = new ConfigObservation
|
||||
public async Task Map_unknown_ignore_false_returns_obs()
|
||||
{
|
||||
Id = Id,
|
||||
Name = "New",
|
||||
Code = "X",
|
||||
CodingSystem = "S"
|
||||
};
|
||||
|
||||
_repo.Setup(r => r.FindById(Id)).ReturnsAsync(ConfigList);
|
||||
_repo.Setup(r => r.Update(It.IsAny<ConfigObservation>())).ReturnsAsync(newCfg);
|
||||
|
||||
var result = await _service.UpdateConfig(newCfg);
|
||||
|
||||
Assert.That(result!.Name, Is.EqualTo("New"));
|
||||
}
|
||||
_settings.Value.ConfigObservation!.IgnoreUnknownObservation = false;
|
||||
_repo.Setup(x => x.FindAll()).ReturnsAsync([]);
|
||||
|
||||
var obs = new BasePatientObservation { Name = "XX" };
|
||||
|
||||
var result = await _service.Map(obs);
|
||||
|
||||
Assert.That(result, Is.EqualTo(obs));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that mapping a patient observation with a value of 14 results in an "Ok" status, confirming the threshold mapping logic returns the expected outcome.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task UpdateConfig_notfound()
|
||||
{
|
||||
_repo
|
||||
.Setup(r => r.FindById(Id))
|
||||
.ReturnsAsync((ConfigObservation?)null);
|
||||
|
||||
Func<Task> act = () => _service.UpdateConfig(new ConfigObservation { Id = Id });
|
||||
|
||||
Assert.ThrowsAsync<NotFoundException>(act);
|
||||
}
|
||||
|
||||
public async Task Map_threshold_Ok()
|
||||
{
|
||||
_repo.Setup(x => x.FindAll()).ReturnsAsync(_allConfigList);
|
||||
|
||||
var obs = new PatientObservation
|
||||
{
|
||||
Name = "SOFA",
|
||||
CodingSystem = "SNM",
|
||||
Value = 14
|
||||
};
|
||||
|
||||
var result = await _service.Map(obs);
|
||||
|
||||
Assert.That(result!.Status, Is.EqualTo(StatusEnum.Type.Ok));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that the Map method returns a Warning status when a patient observation value exceeds the configured threshold.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task CreateConfig_ok()
|
||||
{
|
||||
_repo.Setup(r => r.InsertOneAsyncAndReturn(ConfigList)).Returns(Task.FromResult(ConfigList));
|
||||
|
||||
var result = await _service.CreateConfig(ConfigList);
|
||||
|
||||
Assert.That(result, Is.EqualTo(ConfigList));
|
||||
}
|
||||
public async Task Map_threshold_Warning()
|
||||
{
|
||||
_repo.Setup(x => x.FindAll()).ReturnsAsync(_allConfigList);
|
||||
|
||||
var obs = new PatientObservation
|
||||
{
|
||||
Name = "SOFA",
|
||||
CodingSystem = "SNM",
|
||||
Value = 13
|
||||
};
|
||||
|
||||
var result = await _service.Map(obs);
|
||||
|
||||
Assert.That(result!.Status, Is.EqualTo(StatusEnum.Type.Warning));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that mapping a <see cref="PatientObservation"/> with a SOFA score of 9 through the configured service results in a result with an <see cref="StatusEnum.Type.Alert"/> status.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CreateConfig_duplicate_throws()
|
||||
{
|
||||
_repo.Setup(r => r.FindById(It.IsAny<ObjectId>())).ReturnsAsync(ConfigList);
|
||||
|
||||
|
||||
Func<Task> act = () => _service.CreateConfig(ConfigList);
|
||||
|
||||
Assert.ThrowsAsync<BadRequestException>(act);
|
||||
|
||||
}
|
||||
public async Task Map_threshold_Alert()
|
||||
{
|
||||
_repo.Setup(x => x.FindAll()).ReturnsAsync(_allConfigList);
|
||||
|
||||
var obs = new PatientObservation
|
||||
{
|
||||
Name = "SOFA",
|
||||
CodingSystem = "SNM",
|
||||
Value = 9
|
||||
};
|
||||
|
||||
var result = await _service.Map(obs);
|
||||
|
||||
Assert.That(result!.Status, Is.EqualTo(StatusEnum.Type.Alert));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that mapping a parent <see cref="PatientObservation"/> returns an <see cref="StatusEnum.Type.Ok"/> status
|
||||
/// when the repository successfully locates the configuration by identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task RemoveConfigItem_ok()
|
||||
{
|
||||
var deleted = new ConfigObservation { Id = ObjectId.GenerateNewId(), Name = "X" };
|
||||
|
||||
_repo.Setup(r => r.FindById(It.IsAny<ObjectId>())).ReturnsAsync(ConfigList);
|
||||
_repo.Setup(r => r.Delete(It.IsAny<ObjectId>())).ReturnsAsync(deleted);
|
||||
|
||||
var result = await _service.RemoveConfigItem(ObjectId.GenerateNewId());
|
||||
|
||||
Assert.That(result, Is.EqualTo(deleted));
|
||||
}
|
||||
public async Task Map_parent_ok()
|
||||
{
|
||||
_repo.Setup(x => x.FindById(Id)).ReturnsAsync(ConfigList);
|
||||
|
||||
var fc = new PatientObservation
|
||||
{
|
||||
Id = Id,
|
||||
Name = "FC",
|
||||
Value = 70
|
||||
};
|
||||
|
||||
var result = await _service.Map(fc);
|
||||
|
||||
Assert.That(result!.Status, Is.EqualTo(StatusEnum.Type.Ok));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>UpdateConfig</c> successfully updates an existing configuration and returns the updated <see cref="ConfigObservation"/> with the new name.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task RemoveConfigItem_null()
|
||||
{
|
||||
_repo.Setup(r => r.FindById(Id)).ReturnsAsync(ConfigList);
|
||||
_repo.Setup(r => r.Delete(Id)).ReturnsAsync((ConfigObservation?)null);
|
||||
public async Task UpdateConfig_ok()
|
||||
{
|
||||
var newCfg = new ConfigObservation
|
||||
{
|
||||
Id = Id,
|
||||
Name = "New",
|
||||
Code = "X",
|
||||
CodingSystem = "S"
|
||||
};
|
||||
|
||||
_repo.Setup(r => r.FindById(Id)).ReturnsAsync(ConfigList);
|
||||
_repo.Setup(r => r.Update(It.IsAny<ConfigObservation>())).ReturnsAsync(newCfg);
|
||||
|
||||
var result = await _service.UpdateConfig(newCfg);
|
||||
|
||||
Assert.That(result!.Name, Is.EqualTo("New"));
|
||||
}
|
||||
|
||||
var result = await _service.RemoveConfigItem(Id);
|
||||
/// <summary>
|
||||
/// Verifies that <c>UpdateConfig</c> throws a <see cref="NotFoundException"/> when the target <c>ConfigObservation</c> cannot be found by its identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task UpdateConfig_notfound()
|
||||
{
|
||||
_repo
|
||||
.Setup(r => r.FindById(Id))
|
||||
.ReturnsAsync((ConfigObservation?)null);
|
||||
|
||||
Func<Task> act = () => _service.UpdateConfig(new ConfigObservation { Id = Id });
|
||||
|
||||
Assert.ThrowsAsync<NotFoundException>(act);
|
||||
}
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the <c>CreateConfig</c> service method successfully inserts the provided configuration and returns the expected result.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task CreateConfig_ok()
|
||||
{
|
||||
_repo.Setup(r => r.InsertOneAsyncAndReturn(ConfigList)).Returns(Task.FromResult(ConfigList));
|
||||
|
||||
var result = await _service.CreateConfig(ConfigList);
|
||||
|
||||
Assert.That(result, Is.EqualTo(ConfigList));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="BadRequestException"/> is thrown when attempting to create a configuration that already exists.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CreateConfig_duplicate_throws()
|
||||
{
|
||||
_repo.Setup(r => r.FindById(It.IsAny<ObjectId>())).ReturnsAsync(ConfigList);
|
||||
|
||||
|
||||
Func<Task> act = () => _service.CreateConfig(ConfigList);
|
||||
|
||||
Assert.ThrowsAsync<BadRequestException>(act);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that RemoveConfigItem successfully removes a configuration item and returns the deleted entity when the repository finds and deletes it.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task RemoveConfigItem_ok()
|
||||
{
|
||||
var deleted = new ConfigObservation { Id = ObjectId.GenerateNewId(), Name = "X" };
|
||||
|
||||
_repo.Setup(r => r.FindById(It.IsAny<ObjectId>())).ReturnsAsync(ConfigList);
|
||||
_repo.Setup(r => r.Delete(It.IsAny<ObjectId>())).ReturnsAsync(deleted);
|
||||
|
||||
var result = await _service.RemoveConfigItem(ObjectId.GenerateNewId());
|
||||
|
||||
Assert.That(result, Is.EqualTo(deleted));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>RemoveConfigItem</c> returns <c>null</c> when the underlying delete operation on the repository yields no result, simulating the case where the configuration item does not exist.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task RemoveConfigItem_null()
|
||||
{
|
||||
_repo.Setup(r => r.FindById(Id)).ReturnsAsync(ConfigList);
|
||||
_repo.Setup(r => r.Delete(Id)).ReturnsAsync((ConfigObservation?)null);
|
||||
|
||||
var result = await _service.RemoveConfigItem(Id);
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
}
|
||||
@@ -17,23 +17,26 @@ namespace adas_core.Test.Services;
|
||||
[TestFixture]
|
||||
public class ConfigPumpsServiceTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the test environment by creating mock dependencies and instantiating the <see cref="ConfigPumpsService"/> under test.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
//configPumpsServiceMock = new Mock<IConfigPumpsService>();
|
||||
_configPumpsRepositoryMock = new Mock<IConfigPumpsRepository>();
|
||||
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
_logger = new Mock<ILogger<ConfigPumpsService>>();
|
||||
|
||||
_configPumpsService = new ConfigPumpsService(
|
||||
_configPumpsRepositoryMock.Object,
|
||||
_optionsApiSettings,
|
||||
_logger.Object,
|
||||
_httpContextAccessor.Object,
|
||||
_auditService.Object);
|
||||
}
|
||||
public void Setup()
|
||||
{
|
||||
//configPumpsServiceMock = new Mock<IConfigPumpsService>();
|
||||
_configPumpsRepositoryMock = new Mock<IConfigPumpsRepository>();
|
||||
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
_logger = new Mock<ILogger<ConfigPumpsService>>();
|
||||
|
||||
_configPumpsService = new ConfigPumpsService(
|
||||
_configPumpsRepositoryMock.Object,
|
||||
_optionsApiSettings,
|
||||
_logger.Object,
|
||||
_httpContextAccessor.Object,
|
||||
_auditService.Object);
|
||||
}
|
||||
|
||||
private ConfigPumpsService _configPumpsService;
|
||||
|
||||
@@ -59,112 +62,128 @@ public class ConfigPumpsServiceTest
|
||||
|
||||
private static readonly DateTime Now = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the <see cref="ConfigPumpsService.Map"/> method returns the same <see cref="PumpObservation"/> instance unchanged when the <c>ConfigPumpsRequired</c> option is set to <c>false</c>, bypassing any pump configuration lookup or transformation.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Map_configPumpsRequired_false_Return_same_pump()
|
||||
{
|
||||
_optionsApiSettings.Value.ConfigPumpsRequired = false;
|
||||
|
||||
var pump = new PumpObservation
|
||||
{
|
||||
Code = "code",
|
||||
Name = "name",
|
||||
Time = Now
|
||||
};
|
||||
|
||||
var configPumpsService = new ConfigPumpsService(
|
||||
_configPumpsRepositoryMock.Object,
|
||||
_optionsApiSettings,
|
||||
_logger.Object,
|
||||
_httpContextAccessor.Object,
|
||||
_auditService.Object);
|
||||
|
||||
var result = await configPumpsService.Map(pump);
|
||||
|
||||
Assert.That(pump, Is.EqualTo(result));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Map_not_alarmType_Return_same_pump()
|
||||
{
|
||||
_optionsApiSettings.Value.ConfigPumpsRequired = true;
|
||||
|
||||
var pump = new PumpObservation
|
||||
{
|
||||
Code = "code",
|
||||
Name = "name",
|
||||
Time = Now
|
||||
};
|
||||
|
||||
var result = await _configPumpsService.Map(pump);
|
||||
|
||||
Assert.That(pump, Is.EqualTo(result));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Map_Not_uiConfiguration_Return_same_pump()
|
||||
{
|
||||
_optionsApiSettings.Value.ConfigPumpsRequired = true;
|
||||
|
||||
var pump = new PumpObservation
|
||||
{
|
||||
Code = "code",
|
||||
Name = "name",
|
||||
Time = Now,
|
||||
AlarmType = PumpEnum.AlarmType.Attention
|
||||
};
|
||||
|
||||
var configPumpItem = new ConfigPumpItem();
|
||||
|
||||
var configPumps = new ConfigPumps
|
||||
{
|
||||
Id = "PV1",
|
||||
Items = [configPumpItem]
|
||||
};
|
||||
_configPumpsRepositoryMock.Setup(c => c.FindById(It.IsAny<string>())).ReturnsAsync(configPumps);
|
||||
|
||||
var result = await _configPumpsService.Map(pump);
|
||||
using (Assert.EnterMultipleScope())
|
||||
public async Task Map_configPumpsRequired_false_Return_same_pump()
|
||||
{
|
||||
_optionsApiSettings.Value.ConfigPumpsRequired = false;
|
||||
|
||||
var pump = new PumpObservation
|
||||
{
|
||||
Code = "code",
|
||||
Name = "name",
|
||||
Time = Now
|
||||
};
|
||||
|
||||
var configPumpsService = new ConfigPumpsService(
|
||||
_configPumpsRepositoryMock.Object,
|
||||
_optionsApiSettings,
|
||||
_logger.Object,
|
||||
_httpContextAccessor.Object,
|
||||
_auditService.Object);
|
||||
|
||||
var result = await configPumpsService.Map(pump);
|
||||
|
||||
Assert.That(pump, Is.EqualTo(result));
|
||||
Assert.That(result.UiConfiguration, Is.Null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that when pump configuration is required and the pump has no alarm type,
|
||||
/// the <c>Map</c> method returns the same pump instance unchanged.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Map_uiConfiguration_Return_pump_uiConfiguration()
|
||||
{
|
||||
_optionsApiSettings.Value.ConfigPumpsRequired = true;
|
||||
|
||||
var pump = new PumpObservation
|
||||
public async Task Map_not_alarmType_Return_same_pump()
|
||||
{
|
||||
Code = "code",
|
||||
Name = "name",
|
||||
Time = Now,
|
||||
AlarmType = PumpEnum.AlarmType.AirInLine
|
||||
};
|
||||
_optionsApiSettings.Value.ConfigPumpsRequired = true;
|
||||
|
||||
var pump = new PumpObservation
|
||||
{
|
||||
Code = "code",
|
||||
Name = "name",
|
||||
Time = Now
|
||||
};
|
||||
|
||||
var result = await _configPumpsService.Map(pump);
|
||||
|
||||
Assert.That(pump, Is.EqualTo(result));
|
||||
}
|
||||
|
||||
|
||||
var configPumpItem = new ConfigPumpItem
|
||||
/// <summary>
|
||||
/// Verifies that the <see cref="ConfigPumpsService.Map"/> method returns the original <see cref="PumpObservation"/> unchanged when the configuration pump item is empty, ensuring that no <c>UiConfiguration</c> is assigned in that case.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Map_Not_uiConfiguration_Return_same_pump()
|
||||
{
|
||||
AlarmType = PumpEnum.AlarmType.AirInLine,
|
||||
UiConfiguration = new Dictionary<string, object> { { "screenAlarmLabel", PumpEnum.AlarmType.AirInLine } }
|
||||
};
|
||||
_optionsApiSettings.Value.ConfigPumpsRequired = true;
|
||||
|
||||
var pump = new PumpObservation
|
||||
{
|
||||
Code = "code",
|
||||
Name = "name",
|
||||
Time = Now,
|
||||
AlarmType = PumpEnum.AlarmType.Attention
|
||||
};
|
||||
|
||||
var configPumpItem = new ConfigPumpItem();
|
||||
|
||||
var configPumps = new ConfigPumps
|
||||
{
|
||||
Id = "PV1",
|
||||
Items = [configPumpItem]
|
||||
};
|
||||
_configPumpsRepositoryMock.Setup(c => c.FindById(It.IsAny<string>())).ReturnsAsync(configPumps);
|
||||
|
||||
var result = await _configPumpsService.Map(pump);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(pump, Is.EqualTo(result));
|
||||
Assert.That(result.UiConfiguration, Is.Null);
|
||||
}
|
||||
}
|
||||
|
||||
var configPumps = new ConfigPumps
|
||||
/// <summary>
|
||||
/// Verifies that mapping a <see cref="PumpObservation"/> returns the expected pump UI
|
||||
/// configuration when a matching <see cref="ConfigPumpItem"/> is found for the pump's
|
||||
/// alarm type, ensuring the resulting UI configuration contains the expected label
|
||||
/// entries such as the "screenAlarmLabel" mapped to the alarm type.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Map_uiConfiguration_Return_pump_uiConfiguration()
|
||||
{
|
||||
Id = "PV1",
|
||||
Items = [configPumpItem]
|
||||
};
|
||||
|
||||
_configPumpsRepositoryMock.Setup(c => c.FindById(It.IsAny<string>())).ReturnsAsync(configPumps);
|
||||
|
||||
var result = await _configPumpsService.Map(pump);
|
||||
|
||||
Assert.That(result.UiConfiguration, Is.Not.Null);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(result.UiConfiguration, Has.Count.EqualTo(1));
|
||||
Assert.That(result.UiConfiguration!["screenAlarmLabel"], Is.EqualTo(PumpEnum.AlarmType.AirInLine));
|
||||
};
|
||||
}
|
||||
_optionsApiSettings.Value.ConfigPumpsRequired = true;
|
||||
|
||||
var pump = new PumpObservation
|
||||
{
|
||||
Code = "code",
|
||||
Name = "name",
|
||||
Time = Now,
|
||||
AlarmType = PumpEnum.AlarmType.AirInLine
|
||||
};
|
||||
|
||||
|
||||
var configPumpItem = new ConfigPumpItem
|
||||
{
|
||||
AlarmType = PumpEnum.AlarmType.AirInLine,
|
||||
UiConfiguration = new Dictionary<string, object> { { "screenAlarmLabel", PumpEnum.AlarmType.AirInLine } }
|
||||
};
|
||||
|
||||
var configPumps = new ConfigPumps
|
||||
{
|
||||
Id = "PV1",
|
||||
Items = [configPumpItem]
|
||||
};
|
||||
|
||||
_configPumpsRepositoryMock.Setup(c => c.FindById(It.IsAny<string>())).ReturnsAsync(configPumps);
|
||||
|
||||
var result = await _configPumpsService.Map(pump);
|
||||
|
||||
Assert.That(result.UiConfiguration, Is.Not.Null);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(result.UiConfiguration, Has.Count.EqualTo(1));
|
||||
Assert.That(result.UiConfiguration!["screenAlarmLabel"], Is.EqualTo(PumpEnum.AlarmType.AirInLine));
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -13,21 +13,24 @@ namespace adas_core.Test.Services;
|
||||
[TestFixture]
|
||||
public class ConfigUnitsServiceTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the test dependencies and creates a new instance of <see cref="ConfigUnitsService"/> with mocked repository, options, and logger for use in unit tests.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
//configUnitsServiceMock = new Mock<IConfigUnitsService>();
|
||||
_configUnitsRepositoryMock = new Mock<IConfigUnitsRepository>();
|
||||
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
_logger = new Mock<ILogger<ConfigUnitsService>>();
|
||||
|
||||
_configUnitsService = new ConfigUnitsService(
|
||||
_configUnitsRepositoryMock.Object,
|
||||
_optionsApiSettings,
|
||||
_logger.Object);
|
||||
}
|
||||
public void Setup()
|
||||
{
|
||||
//configUnitsServiceMock = new Mock<IConfigUnitsService>();
|
||||
_configUnitsRepositoryMock = new Mock<IConfigUnitsRepository>();
|
||||
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
|
||||
_logger = new Mock<ILogger<ConfigUnitsService>>();
|
||||
|
||||
_configUnitsService = new ConfigUnitsService(
|
||||
_configUnitsRepositoryMock.Object,
|
||||
_optionsApiSettings,
|
||||
_logger.Object);
|
||||
}
|
||||
|
||||
private ConfigUnitsService _configUnitsService;
|
||||
|
||||
@@ -48,110 +51,123 @@ public class ConfigUnitsServiceTest
|
||||
|
||||
private static readonly DateTime Now = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that when <c>ConfigUnitsRequired</c> is set to <c>false</c>, the <see cref="ConfigUnitsService.Map"/> method returns the same observation instance without applying any unit mapping or transformation.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Map_configUnitsRequired_false_Return_same_obs()
|
||||
{
|
||||
_optionsApiSettings.Value.ConfigUnitsRequired = false;
|
||||
|
||||
var obs = new PatientObservation
|
||||
{
|
||||
Code = "code",
|
||||
CodingSystem = "SNM",
|
||||
Name = "name",
|
||||
Time = Now
|
||||
};
|
||||
|
||||
var configUnitsService = new ConfigUnitsService(
|
||||
_configUnitsRepositoryMock.Object,
|
||||
_optionsApiSettings,
|
||||
_logger.Object);
|
||||
|
||||
var result = await configUnitsService.Map(obs);
|
||||
|
||||
Assert.That(obs, Is.EqualTo(result));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Map_not_units_Return_same_obs()
|
||||
{
|
||||
_optionsApiSettings.Value.ConfigUnitsRequired = true;
|
||||
|
||||
var obs = new PatientObservation
|
||||
{
|
||||
Code = "code",
|
||||
CodingSystem = "SNM",
|
||||
Name = "name",
|
||||
Time = Now
|
||||
};
|
||||
|
||||
var result = await _configUnitsService.Map(obs);
|
||||
|
||||
Assert.That(obs, Is.EqualTo(result));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Map_Not_Find_Config_Return_same_obs()
|
||||
{
|
||||
_optionsApiSettings.Value.ConfigUnitsRequired = true;
|
||||
|
||||
var obs = new PatientObservation
|
||||
{
|
||||
Code = "code",
|
||||
CodingSystem = "SNM",
|
||||
Name = "name",
|
||||
Time = Now
|
||||
};
|
||||
|
||||
var configUnitItem = new ConfigUnitItem();
|
||||
|
||||
var configUnits = new ConfigUnits
|
||||
{
|
||||
Id = "PV1",
|
||||
Items = [configUnitItem]
|
||||
};
|
||||
|
||||
_configUnitsRepositoryMock.Setup(c => c.FindById(It.IsAny<string>())).ReturnsAsync(configUnits);
|
||||
|
||||
var result = await _configUnitsService.Map(obs);
|
||||
using (Assert.EnterMultipleScope())
|
||||
public async Task Map_configUnitsRequired_false_Return_same_obs()
|
||||
{
|
||||
_optionsApiSettings.Value.ConfigUnitsRequired = false;
|
||||
|
||||
var obs = new PatientObservation
|
||||
{
|
||||
Code = "code",
|
||||
CodingSystem = "SNM",
|
||||
Name = "name",
|
||||
Time = Now
|
||||
};
|
||||
|
||||
var configUnitsService = new ConfigUnitsService(
|
||||
_configUnitsRepositoryMock.Object,
|
||||
_optionsApiSettings,
|
||||
_logger.Object);
|
||||
|
||||
var result = await configUnitsService.Map(obs);
|
||||
|
||||
Assert.That(obs, Is.EqualTo(result));
|
||||
Assert.That(result.Units, Is.Null);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that mapping a patient observation that does not contain units returns the same observation unchanged, confirming the mapping logic preserves the original data when no unit conversion is applicable.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Map_configUnits_Return_obs_ConfigUnit()
|
||||
{
|
||||
_optionsApiSettings.Value.ConfigUnitsRequired = true;
|
||||
|
||||
var obs = new PatientObservation
|
||||
public async Task Map_not_units_Return_same_obs()
|
||||
{
|
||||
Code = "code",
|
||||
CodingSystem = "SNM",
|
||||
Name = "name",
|
||||
Time = Now,
|
||||
Units = "MDC_DIM_X_G_PER_KG"
|
||||
};
|
||||
_optionsApiSettings.Value.ConfigUnitsRequired = true;
|
||||
|
||||
var obs = new PatientObservation
|
||||
{
|
||||
Code = "code",
|
||||
CodingSystem = "SNM",
|
||||
Name = "name",
|
||||
Time = Now
|
||||
};
|
||||
|
||||
var result = await _configUnitsService.Map(obs);
|
||||
|
||||
Assert.That(obs, Is.EqualTo(result));
|
||||
}
|
||||
|
||||
|
||||
var configUnitItem = new ConfigUnitItem
|
||||
/// <summary>
|
||||
/// Verifies that the Map method returns the original observation unchanged with a null Units property when configuration units are required and no matching config unit is found for the observation's code.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Map_Not_Find_Config_Return_same_obs()
|
||||
{
|
||||
Code = "MDC_DIM_X_G_PER_KG",
|
||||
Value = "g/kg"
|
||||
};
|
||||
_optionsApiSettings.Value.ConfigUnitsRequired = true;
|
||||
|
||||
var obs = new PatientObservation
|
||||
{
|
||||
Code = "code",
|
||||
CodingSystem = "SNM",
|
||||
Name = "name",
|
||||
Time = Now
|
||||
};
|
||||
|
||||
var configUnitItem = new ConfigUnitItem();
|
||||
|
||||
var configUnits = new ConfigUnits
|
||||
{
|
||||
Id = "PV1",
|
||||
Items = [configUnitItem]
|
||||
};
|
||||
|
||||
_configUnitsRepositoryMock.Setup(c => c.FindById(It.IsAny<string>())).ReturnsAsync(configUnits);
|
||||
|
||||
var result = await _configUnitsService.Map(obs);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(obs, Is.EqualTo(result));
|
||||
Assert.That(result.Units, Is.Null);
|
||||
};
|
||||
}
|
||||
|
||||
var configUnits = new ConfigUnits
|
||||
/// <summary>
|
||||
/// Verifies that Map returns the configured unit value for a patient observation when
|
||||
/// ConfigUnitsRequired is enabled and a matching config unit is found in the repository.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Map_configUnits_Return_obs_ConfigUnit()
|
||||
{
|
||||
Id = "PV1",
|
||||
Items = [configUnitItem]
|
||||
};
|
||||
|
||||
_configUnitsRepositoryMock.Setup(c => c.FindById(It.IsAny<string>())).ReturnsAsync(configUnits);
|
||||
|
||||
var result = await _configUnitsService.Map(obs);
|
||||
|
||||
Assert.That(result.Units, Is.Not.Null);
|
||||
Assert.That(result.Units, Is.EqualTo("g/kg"));
|
||||
}
|
||||
_optionsApiSettings.Value.ConfigUnitsRequired = true;
|
||||
|
||||
var obs = new PatientObservation
|
||||
{
|
||||
Code = "code",
|
||||
CodingSystem = "SNM",
|
||||
Name = "name",
|
||||
Time = Now,
|
||||
Units = "MDC_DIM_X_G_PER_KG"
|
||||
};
|
||||
|
||||
|
||||
var configUnitItem = new ConfigUnitItem
|
||||
{
|
||||
Code = "MDC_DIM_X_G_PER_KG",
|
||||
Value = "g/kg"
|
||||
};
|
||||
|
||||
var configUnits = new ConfigUnits
|
||||
{
|
||||
Id = "PV1",
|
||||
Items = [configUnitItem]
|
||||
};
|
||||
|
||||
_configUnitsRepositoryMock.Setup(c => c.FindById(It.IsAny<string>())).ReturnsAsync(configUnits);
|
||||
|
||||
var result = await _configUnitsService.Map(obs);
|
||||
|
||||
Assert.That(result.Units, Is.Not.Null);
|
||||
Assert.That(result.Units, Is.EqualTo("g/kg"));
|
||||
}
|
||||
}
|
||||
@@ -17,51 +17,54 @@ namespace adas_core.Test.Services;
|
||||
[TestFixture]
|
||||
public class DiagnosisServiceTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the mocked dependencies (patient, diagnosis, unit, audit, subscribers and calculated observations services along with their repositories) and constructs the <see cref="DiagnosisService"/> instance under test.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_patientServiceMock = new Mock<IPatientService>();
|
||||
_patientServiceLazy = new Lazy<IPatientService>(() => _patientServiceMock.Object);
|
||||
|
||||
//var sectionServiceMock = new Mock<ISectionService>();
|
||||
//sectionServiceLazy = new Lazy<ISectionService>(() => sectionServiceMock.Object);
|
||||
|
||||
_diagnosisRepositoryMock = new Mock<IDiagnosisRepository>();
|
||||
_diagnosisArchiveRepositoryMock = new Mock<IDiagnosisArchiveRepository>();
|
||||
_clientMessageServiceMock = new Mock<IClientMessageService>();
|
||||
_subscribersServiceMock = new Mock<ISubscribersService>();
|
||||
_unitServiceMock = new Mock<IUnitService>();
|
||||
_httpContextAccessor = new Mock<IHttpContextAccessor>();
|
||||
_auditService = new Mock<ILocalAuditService>();
|
||||
_calculatedObservationsServiceMock = new Mock<ICalculatedObservationsService>();
|
||||
_calculatedObservationsServiceLazy =
|
||||
new Lazy<ICalculatedObservationsService>(() => _calculatedObservationsServiceMock.Object);
|
||||
_calculatedObservationsServiceMock.Setup(x => x.Map(It.IsAny<PatientDiagnosis>()))
|
||||
.ReturnsAsync((PatientDiagnosis? value) => value);
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
_logger = new Mock<ILogger<DiagnosisService>>();
|
||||
_diagnosisService = new DiagnosisService(
|
||||
_patientServiceLazy,
|
||||
//sectionServiceLazy,
|
||||
_optionsApiSettings,
|
||||
_diagnosisRepositoryMock.Object,
|
||||
_diagnosisArchiveRepositoryMock.Object,
|
||||
_logger.Object,
|
||||
_clientMessageServiceMock.Object,
|
||||
_subscribersServiceMock.Object,
|
||||
_calculatedObservationsServiceLazy,
|
||||
_httpContextAccessor.Object,
|
||||
_auditService.Object,
|
||||
_unitServiceMock.Object
|
||||
);
|
||||
|
||||
|
||||
// Create a mock of the singleton class subscribers
|
||||
var mockSingleton = new Mock<ICalculatedObservationsService>();
|
||||
|
||||
// Set up the mock object to return a specific value when a method is called
|
||||
mockSingleton.Setup(x => x.Map(It.IsAny<PatientDiagnosis>())).ReturnsAsync((PatientDiagnosis? value) => value);
|
||||
}
|
||||
public void Setup()
|
||||
{
|
||||
_patientServiceMock = new Mock<IPatientService>();
|
||||
_patientServiceLazy = new Lazy<IPatientService>(() => _patientServiceMock.Object);
|
||||
|
||||
//var sectionServiceMock = new Mock<ISectionService>();
|
||||
//sectionServiceLazy = new Lazy<ISectionService>(() => sectionServiceMock.Object);
|
||||
|
||||
_diagnosisRepositoryMock = new Mock<IDiagnosisRepository>();
|
||||
_diagnosisArchiveRepositoryMock = new Mock<IDiagnosisArchiveRepository>();
|
||||
_clientMessageServiceMock = new Mock<IClientMessageService>();
|
||||
_subscribersServiceMock = new Mock<ISubscribersService>();
|
||||
_unitServiceMock = new Mock<IUnitService>();
|
||||
_httpContextAccessor = new Mock<IHttpContextAccessor>();
|
||||
_auditService = new Mock<ILocalAuditService>();
|
||||
_calculatedObservationsServiceMock = new Mock<ICalculatedObservationsService>();
|
||||
_calculatedObservationsServiceLazy =
|
||||
new Lazy<ICalculatedObservationsService>(() => _calculatedObservationsServiceMock.Object);
|
||||
_calculatedObservationsServiceMock.Setup(x => x.Map(It.IsAny<PatientDiagnosis>()))
|
||||
.ReturnsAsync((PatientDiagnosis? value) => value);
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
_logger = new Mock<ILogger<DiagnosisService>>();
|
||||
_diagnosisService = new DiagnosisService(
|
||||
_patientServiceLazy,
|
||||
//sectionServiceLazy,
|
||||
_optionsApiSettings,
|
||||
_diagnosisRepositoryMock.Object,
|
||||
_diagnosisArchiveRepositoryMock.Object,
|
||||
_logger.Object,
|
||||
_clientMessageServiceMock.Object,
|
||||
_subscribersServiceMock.Object,
|
||||
_calculatedObservationsServiceLazy,
|
||||
_httpContextAccessor.Object,
|
||||
_auditService.Object,
|
||||
_unitServiceMock.Object
|
||||
);
|
||||
|
||||
|
||||
// Create a mock of the singleton class subscribers
|
||||
var mockSingleton = new Mock<ICalculatedObservationsService>();
|
||||
|
||||
// Set up the mock object to return a specific value when a method is called
|
||||
mockSingleton.Setup(x => x.Map(It.IsAny<PatientDiagnosis>())).ReturnsAsync((PatientDiagnosis? value) => value);
|
||||
}
|
||||
|
||||
private DiagnosisService _diagnosisService;
|
||||
|
||||
@@ -137,69 +140,78 @@ public class DiagnosisServiceTest
|
||||
// }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>SaveRequest</c> does not insert a diagnosis when the patient referenced by the <see cref="ApiRequest"/> cannot be found.
|
||||
/// </summary>
|
||||
/// <returns>A task representing the asynchronous test execution.</returns>
|
||||
[Test]
|
||||
public async Task SaveRequest_Not_FindPatient_Return_not_insert()
|
||||
{
|
||||
var apiRequest = new ApiRequest
|
||||
public async Task SaveRequest_Not_FindPatient_Return_not_insert()
|
||||
{
|
||||
Location = new PatientLocation("UCI5C", "Box4"),
|
||||
PatientNumber = "437537",
|
||||
Type = "ORU_R01",
|
||||
PatientId = PatientId.ToString(),
|
||||
MessageTime = Now
|
||||
};
|
||||
|
||||
_patientServiceMock.Setup(cm => cm.FindPatientByApiRequest(apiRequest)).ReturnsAsync((Patient?)null);
|
||||
|
||||
await _diagnosisService.SaveRequest(apiRequest, null);
|
||||
|
||||
_diagnosisRepositoryMock.Verify(d => d.InsertOneAsync(It.IsAny<PatientDiagnosis>()), Times.Never);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task SaveRequest_Not_Observations_Return_not_insert()
|
||||
{
|
||||
var patientObs = new Person
|
||||
{
|
||||
FirstName = "Miguel",
|
||||
LastName = "Villanueva",
|
||||
Ids = new Dictionary<string, string> { { "MR", "437537" } }
|
||||
};
|
||||
|
||||
var patient = new Patient
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
UnitString = "UCI5C",
|
||||
Bed = "Box4",
|
||||
PatientNumber = "437537",
|
||||
Person = patientObs
|
||||
};
|
||||
|
||||
var apiRequest = new ApiRequest
|
||||
{
|
||||
Location = new PatientLocation("UCI5C", "Box4"),
|
||||
ObservationData = new ObservationData
|
||||
var apiRequest = new ApiRequest
|
||||
{
|
||||
Code = "302147001",
|
||||
CodingSystem = "SNM",
|
||||
Value = "Aire; Contacto; Preventivo",
|
||||
Text = "Aislamiento",
|
||||
Time = Now
|
||||
},
|
||||
Patient = patientObs,
|
||||
PatientNumber = "437537",
|
||||
Type = "ORU_R01",
|
||||
PatientId = PatientId.ToString(),
|
||||
MessageTime = Now
|
||||
};
|
||||
Location = new PatientLocation("UCI5C", "Box4"),
|
||||
PatientNumber = "437537",
|
||||
Type = "ORU_R01",
|
||||
PatientId = PatientId.ToString(),
|
||||
MessageTime = Now
|
||||
};
|
||||
|
||||
_patientServiceMock.Setup(cm => cm.FindPatientByApiRequest(apiRequest)).ReturnsAsync((Patient?)null);
|
||||
|
||||
await _diagnosisService.SaveRequest(apiRequest, null);
|
||||
|
||||
_diagnosisRepositoryMock.Verify(d => d.InsertOneAsync(It.IsAny<PatientDiagnosis>()), Times.Never);
|
||||
}
|
||||
|
||||
|
||||
_patientServiceMock.Setup(cm => cm.FindPatientByApiRequest(apiRequest)).ReturnsAsync(patient);
|
||||
|
||||
await _diagnosisService.SaveRequest(apiRequest, null);
|
||||
|
||||
_diagnosisRepositoryMock.Verify(d => d.InsertOneAsync(It.IsAny<PatientDiagnosis>()), Times.Never);
|
||||
}
|
||||
/// <summary>
|
||||
/// Verifies that <c>SaveRequest</c> does not insert a <see cref="PatientDiagnosis"/> when the provided <see cref="ApiRequest"/> is not considered an observation request, ensuring observations must be present to trigger a database insertion.
|
||||
/// </summary>
|
||||
/// <param name="apiRequest">The API request containing the patient and observation data being evaluated.</param>
|
||||
/// <param name="null">Reserved parameter passed to <c>SaveRequest</c> as a null value.</param>
|
||||
[Test]
|
||||
public async Task SaveRequest_Not_Observations_Return_not_insert()
|
||||
{
|
||||
var patientObs = new Person
|
||||
{
|
||||
FirstName = "Miguel",
|
||||
LastName = "Villanueva",
|
||||
Ids = new Dictionary<string, string> { { "MR", "437537" } }
|
||||
};
|
||||
|
||||
var patient = new Patient
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
UnitString = "UCI5C",
|
||||
Bed = "Box4",
|
||||
PatientNumber = "437537",
|
||||
Person = patientObs
|
||||
};
|
||||
|
||||
var apiRequest = new ApiRequest
|
||||
{
|
||||
Location = new PatientLocation("UCI5C", "Box4"),
|
||||
ObservationData = new ObservationData
|
||||
{
|
||||
Code = "302147001",
|
||||
CodingSystem = "SNM",
|
||||
Value = "Aire; Contacto; Preventivo",
|
||||
Text = "Aislamiento",
|
||||
Time = Now
|
||||
},
|
||||
Patient = patientObs,
|
||||
PatientNumber = "437537",
|
||||
Type = "ORU_R01",
|
||||
PatientId = PatientId.ToString(),
|
||||
MessageTime = Now
|
||||
};
|
||||
|
||||
|
||||
_patientServiceMock.Setup(cm => cm.FindPatientByApiRequest(apiRequest)).ReturnsAsync(patient);
|
||||
|
||||
await _diagnosisService.SaveRequest(apiRequest, null);
|
||||
|
||||
_diagnosisRepositoryMock.Verify(d => d.InsertOneAsync(It.IsAny<PatientDiagnosis>()), Times.Never);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task SaveRequest_Not_DiagnosisCodeSettings_Return_not_insert()
|
||||
|
||||
@@ -13,6 +13,9 @@ using Moq;
|
||||
|
||||
namespace adas_core.Test.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Provides unit tests for the <see cref="DischargeService"/> class, verifying the behavior and correctness of discharge-related operations.
|
||||
/// </summary>
|
||||
public class DischargeServiceTest
|
||||
{
|
||||
private readonly Mock<ILocalAuditService> _auditServiceMock = new();
|
||||
@@ -28,47 +31,55 @@ public class DischargeServiceTest
|
||||
private readonly Mock<IUnitService> _unitServiceMock = new();
|
||||
private DischargeService _dischargeService = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Sets up the test environment by creating a mock authenticated user context and instantiating the <see cref="DischargeService"/> with its required dependencies for use in unit tests.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
var userClaims = new ClaimsPrincipal(new ClaimsIdentity([
|
||||
new Claim(ClaimTypes.Name, "TestUser")
|
||||
], "mock"));
|
||||
|
||||
var httpContextMock = new DefaultHttpContext
|
||||
public void Setup()
|
||||
{
|
||||
User = userClaims
|
||||
};
|
||||
|
||||
_httpContextAccessorMock.Setup(accessor => accessor.HttpContext)
|
||||
.Returns(httpContextMock);
|
||||
_dischargeService = new DischargeService(
|
||||
_loggerMock.Object,
|
||||
_subscribersServiceMock.Object,
|
||||
_dischargeRepositoryMock.Object,
|
||||
_patientServiceLazyMock.Object,
|
||||
_clientMessageServiceMock.Object,
|
||||
_pointOfCareServiceMock.Object,
|
||||
_httpContextAccessorMock.Object,
|
||||
_auditServiceMock.Object,
|
||||
_unitServiceMock.Object,
|
||||
_masterMock.Object);
|
||||
}
|
||||
var userClaims = new ClaimsPrincipal(new ClaimsIdentity([
|
||||
new Claim(ClaimTypes.Name, "TestUser")
|
||||
], "mock"));
|
||||
|
||||
var httpContextMock = new DefaultHttpContext
|
||||
{
|
||||
User = userClaims
|
||||
};
|
||||
|
||||
_httpContextAccessorMock.Setup(accessor => accessor.HttpContext)
|
||||
.Returns(httpContextMock);
|
||||
_dischargeService = new DischargeService(
|
||||
_loggerMock.Object,
|
||||
_subscribersServiceMock.Object,
|
||||
_dischargeRepositoryMock.Object,
|
||||
_patientServiceLazyMock.Object,
|
||||
_clientMessageServiceMock.Object,
|
||||
_pointOfCareServiceMock.Object,
|
||||
_httpContextAccessorMock.Object,
|
||||
_auditServiceMock.Object,
|
||||
_unitServiceMock.Object,
|
||||
_masterMock.Object);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="DischargeService.DeleteDischargeAsync(Discharge)"/> successfully deletes a discharge
|
||||
/// when it exists in the repository.
|
||||
/// </summary>
|
||||
/// <param name="discharge">The discharge entity expected to be deleted; its identifier is used to invoke the repository delete operation.</param>
|
||||
[Test]
|
||||
public async Task DeleteDischargeAsync_WhenDischargeExists_DeletesDischarge()
|
||||
{
|
||||
// Arrange
|
||||
var dischargeId = ObjectId.GenerateNewId();
|
||||
var discharge = new Discharge { Id = dischargeId };
|
||||
_dischargeRepositoryMock.Setup(repo => repo.FindById(dischargeId)).ReturnsAsync(discharge);
|
||||
|
||||
// Act
|
||||
await _dischargeService.DeleteDischargeAsync(discharge);
|
||||
|
||||
// Assert
|
||||
_dischargeRepositoryMock.Verify(repo => repo.Delete(dischargeId), Times.Once);
|
||||
}
|
||||
public async Task DeleteDischargeAsync_WhenDischargeExists_DeletesDischarge()
|
||||
{
|
||||
// Arrange
|
||||
var dischargeId = ObjectId.GenerateNewId();
|
||||
var discharge = new Discharge { Id = dischargeId };
|
||||
_dischargeRepositoryMock.Setup(repo => repo.FindById(dischargeId)).ReturnsAsync(discharge);
|
||||
|
||||
// Act
|
||||
await _dischargeService.DeleteDischargeAsync(discharge);
|
||||
|
||||
// Assert
|
||||
_dischargeRepositoryMock.Verify(repo => repo.Delete(dischargeId), Times.Once);
|
||||
}
|
||||
|
||||
//necesita el pocservice
|
||||
// [Test]
|
||||
@@ -86,32 +97,39 @@ public class DischargeServiceTest
|
||||
// Assert.That(result, Is.EqualTo(discharge));
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="DischargeService.GetDischargeByIdAsync"/> throws a <see cref="NotFoundException"/> when the requested discharge is not found.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void GetDischargeByIdAsync_WhenExceptionOccurs_ReturnsNullAndLogsError()
|
||||
{
|
||||
// Arrange
|
||||
var dischargeId = ObjectId.GenerateNewId();
|
||||
// Act and assert
|
||||
Func<Task> act = async () => await _dischargeService.GetDischargeByIdAsync(dischargeId);
|
||||
Assert.ThrowsAsync<NotFoundException>(act);
|
||||
}
|
||||
public void GetDischargeByIdAsync_WhenExceptionOccurs_ReturnsNullAndLogsError()
|
||||
{
|
||||
// Arrange
|
||||
var dischargeId = ObjectId.GenerateNewId();
|
||||
// Act and assert
|
||||
Func<Task> act = async () => await _dischargeService.GetDischargeByIdAsync(dischargeId);
|
||||
Assert.ThrowsAsync<NotFoundException>(act);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the discharge service returns the expected discharges retrieved from the repository when the underlying repository call completes successfully without exceptions.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous test execution.</returns>
|
||||
[Test]
|
||||
public async Task GetDischargesAsync_WhenNoException_ReturnsDischarges()
|
||||
{
|
||||
// Arrange
|
||||
var discharge = TestUtilities.CreateValidDischarge();
|
||||
var discharges = new List<Discharge> { discharge };
|
||||
_dischargeRepositoryMock.Setup(repo => repo.FindAll()).ReturnsAsync(discharges);
|
||||
|
||||
// Act
|
||||
var result = await _dischargeService.GetDischargesAsync();
|
||||
|
||||
var resultList = result.ToList();
|
||||
|
||||
// Assert
|
||||
Assert.That(resultList.First().Id, Is.EqualTo(discharges.First().Id));
|
||||
}
|
||||
public async Task GetDischargesAsync_WhenNoException_ReturnsDischarges()
|
||||
{
|
||||
// Arrange
|
||||
var discharge = TestUtilities.CreateValidDischarge();
|
||||
var discharges = new List<Discharge> { discharge };
|
||||
_dischargeRepositoryMock.Setup(repo => repo.FindAll()).ReturnsAsync(discharges);
|
||||
|
||||
// Act
|
||||
var result = await _dischargeService.GetDischargesAsync();
|
||||
|
||||
var resultList = result.ToList();
|
||||
|
||||
// Assert
|
||||
Assert.That(resultList.First().Id, Is.EqualTo(discharges.First().Id));
|
||||
}
|
||||
|
||||
//necesita el pocservice
|
||||
// [Test]
|
||||
@@ -128,64 +146,78 @@ public class DischargeServiceTest
|
||||
// Assert.That(result?.Id, Is.EqualTo(discharge.Id));
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="DischargeService.InsertDischarge"/> returns the inserted discharge
|
||||
/// when the underlying repository successfully completes the insertion and the entity can be retrieved by its identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task InsertDischarge_WhenInsertionSuccessful_ReturnsInsertedDischarge()
|
||||
{
|
||||
// Arrange
|
||||
var dischargeId = ObjectId.GenerateNewId();
|
||||
var discharge = new Discharge { Id = dischargeId };
|
||||
_dischargeRepositoryMock.Setup(repo => repo.InsertOneAsync(discharge)).Returns(Task.CompletedTask);
|
||||
_dischargeRepositoryMock.Setup(repo => repo.FindById(dischargeId)).ReturnsAsync(discharge);
|
||||
|
||||
// Act
|
||||
var result = await _dischargeService.InsertDischarge(discharge);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(discharge));
|
||||
}
|
||||
public async Task InsertDischarge_WhenInsertionSuccessful_ReturnsInsertedDischarge()
|
||||
{
|
||||
// Arrange
|
||||
var dischargeId = ObjectId.GenerateNewId();
|
||||
var discharge = new Discharge { Id = dischargeId };
|
||||
_dischargeRepositoryMock.Setup(repo => repo.InsertOneAsync(discharge)).Returns(Task.CompletedTask);
|
||||
_dischargeRepositoryMock.Setup(repo => repo.FindById(dischargeId)).ReturnsAsync(discharge);
|
||||
|
||||
// Act
|
||||
var result = await _dischargeService.InsertDischarge(discharge);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(discharge));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="DischargeService.InsertDischarge"/> handles repository insertion failures by propagating the exception thrown by the underlying data store.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void InsertDischarge_WhenInsertionFails_ReturnsNullAndLogsError()
|
||||
{
|
||||
// Arrange
|
||||
var discharge = new Discharge { Id = ObjectId.GenerateNewId() };
|
||||
var exception = new Exception("Failed to insert discharge");
|
||||
_dischargeRepositoryMock.Setup(repo => repo.InsertOneAsync(discharge)).ThrowsAsync(exception);
|
||||
|
||||
// Assert
|
||||
Func<Task> act = async () => await _dischargeService.InsertDischarge(discharge);
|
||||
Assert.ThrowsAsync<Exception>(act);
|
||||
}
|
||||
public void InsertDischarge_WhenInsertionFails_ReturnsNullAndLogsError()
|
||||
{
|
||||
// Arrange
|
||||
var discharge = new Discharge { Id = ObjectId.GenerateNewId() };
|
||||
var exception = new Exception("Failed to insert discharge");
|
||||
_dischargeRepositoryMock.Setup(repo => repo.InsertOneAsync(discharge)).ThrowsAsync(exception);
|
||||
|
||||
// Assert
|
||||
Func<Task> act = async () => await _dischargeService.InsertDischarge(discharge);
|
||||
Assert.ThrowsAsync<Exception>(act);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="DischargeService.GetDischargeByLocation"/> returns the discharge
|
||||
/// retrieved from the repository when a discharge exists for the specified patient location.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetDischargeByLocation_WhenDischargeExists_ReturnsDischarge()
|
||||
{
|
||||
// Arrange
|
||||
var location = new PatientLocation("UnitName", "Bed", "Room");
|
||||
var discharge = new Discharge();
|
||||
_dischargeRepositoryMock.Setup(repo => repo.GetDischargeByLocation(location)).ReturnsAsync(discharge);
|
||||
|
||||
// Act
|
||||
var result = await _dischargeService.GetDischargeByLocation(location);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(discharge));
|
||||
}
|
||||
public async Task GetDischargeByLocation_WhenDischargeExists_ReturnsDischarge()
|
||||
{
|
||||
// Arrange
|
||||
var location = new PatientLocation("UnitName", "Bed", "Room");
|
||||
var discharge = new Discharge();
|
||||
_dischargeRepositoryMock.Setup(repo => repo.GetDischargeByLocation(location)).ReturnsAsync(discharge);
|
||||
|
||||
// Act
|
||||
var result = await _dischargeService.GetDischargeByLocation(location);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(discharge));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="IDischargeService.GetDischargeByLocation"/> returns <c>null</c> when the underlying discharge repository throws an exception while retrieving the discharge record for the specified patient location.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetDischargeByLocation_WhenExceptionOccurs_ReturnsNullAndLogsError()
|
||||
{
|
||||
// Arrange
|
||||
var location = new PatientLocation("UnitName", "Bed", "Room");
|
||||
var exception = new Exception("Failed to retrieve discharge by location");
|
||||
_dischargeRepositoryMock.Setup(repo => repo.GetDischargeByLocation(location)).ThrowsAsync(exception);
|
||||
|
||||
// Act
|
||||
var result = await _dischargeService.GetDischargeByLocation(location);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
public async Task GetDischargeByLocation_WhenExceptionOccurs_ReturnsNullAndLogsError()
|
||||
{
|
||||
// Arrange
|
||||
var location = new PatientLocation("UnitName", "Bed", "Room");
|
||||
var exception = new Exception("Failed to retrieve discharge by location");
|
||||
_dischargeRepositoryMock.Setup(repo => repo.GetDischargeByLocation(location)).ThrowsAsync(exception);
|
||||
|
||||
// Act
|
||||
var result = await _dischargeService.GetDischargeByLocation(location);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
// [Test]
|
||||
// public async Task GetDischargeByPointOfCareId_WhenDischargeExists_ReturnsDischarge()
|
||||
@@ -201,18 +233,21 @@ public class DischargeServiceTest
|
||||
// Assert.That(result, Is.EqualTo(discharge));
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="DischargeService.GetDischargeByPointOfCareId"/> returns <c>null</c> when the underlying repository throws an exception while attempting to retrieve a discharge by its point-of-care identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetDischargeByPointOfCareId_WhenExceptionOccurs_ReturnsNullAndLogsError()
|
||||
{
|
||||
// Arrange
|
||||
var poc = ObjectId.GenerateNewId();
|
||||
var exception = new Exception("Failed to retrieve discharge by PointOfCareId");
|
||||
_dischargeRepositoryMock.Setup(repo => repo.GetDischargeByPointOfCareId(poc)).ThrowsAsync(exception);
|
||||
|
||||
// Act
|
||||
var result = await _dischargeService.GetDischargeByPointOfCareId(poc);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
public async Task GetDischargeByPointOfCareId_WhenExceptionOccurs_ReturnsNullAndLogsError()
|
||||
{
|
||||
// Arrange
|
||||
var poc = ObjectId.GenerateNewId();
|
||||
var exception = new Exception("Failed to retrieve discharge by PointOfCareId");
|
||||
_dischargeRepositoryMock.Setup(repo => repo.GetDischargeByPointOfCareId(poc)).ThrowsAsync(exception);
|
||||
|
||||
// Act
|
||||
var result = await _dischargeService.GetDischargeByPointOfCareId(poc);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,10 @@ public class DisplayServiceTest
|
||||
|
||||
private DisplayService _displayService = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes mocked dependencies and configuration required to construct a <see cref="DisplayService"/> instance for unit tests.
|
||||
/// Sets up the HTTP context with a test user claim, creates default cache settings, and wires all collaborators (repositories, services, logger, permissions) into the service under test.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
@@ -56,7 +60,7 @@ public class DisplayServiceTest
|
||||
_httpContextAccessorMock.Setup(a => a.HttpContext).Returns(new DefaultHttpContext { User = claims });
|
||||
|
||||
var cacheSettings = Options.Create(new CacheSettings());
|
||||
|
||||
|
||||
_displayService = new DisplayService(
|
||||
_mockDisplayRepository.Object,
|
||||
_mockPointOfCareService.Object,
|
||||
@@ -73,12 +77,15 @@ public class DisplayServiceTest
|
||||
_mockCacheService.Object,
|
||||
cacheSettings
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------
|
||||
// InsertOne
|
||||
// -----------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="DisplayService.InsertOne"/> inserts a display by resolving the default configuration for its type and persisting it through the repository's insert method.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task InsertOne_ShouldInsertDisplay()
|
||||
{
|
||||
@@ -104,6 +111,9 @@ public class DisplayServiceTest
|
||||
// -----------------------------------------------------------
|
||||
// GetById
|
||||
// -----------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that the <see cref="DisplayService"/> returns the expected <see cref="Display"/> instance when a matching id is provided through the repository.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetById_ShouldReturnDisplay()
|
||||
{
|
||||
@@ -120,6 +130,9 @@ public class DisplayServiceTest
|
||||
// -----------------------------------------------------------
|
||||
// GetAllByUser - userName null
|
||||
// -----------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that _displayService.GetAllByUser returns an empty collection when the user name is null.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetAllByUser_ShouldReturnEmpty_WhenUserNameNull()
|
||||
{
|
||||
@@ -130,7 +143,7 @@ public class DisplayServiceTest
|
||||
// -----------------------------------------------------------
|
||||
// GetAllByUser - Admin case
|
||||
// -----------------------------------------------------------
|
||||
|
||||
|
||||
[Test]
|
||||
public async Task GetAllByUser_ShouldReturnDisplays_WhenAdmin()
|
||||
{
|
||||
@@ -144,7 +157,7 @@ public class DisplayServiceTest
|
||||
{
|
||||
Id = adminId,
|
||||
UserName = userName,
|
||||
Authorization =
|
||||
Authorization =
|
||||
[
|
||||
new Authorization { UnitId = unitId.ToString(), Rol = nameof(PermissionEnum.RolesType.AuthAdmin) }
|
||||
]
|
||||
@@ -182,13 +195,13 @@ public class DisplayServiceTest
|
||||
_mockPermissionService
|
||||
.Setup(p => p.GetPermissionsForUnit(unitId.ToString(), user))
|
||||
.ReturnsAsync(new DisplayPermissionTypes(
|
||||
new UserActions(true,true,true,true,true),
|
||||
new UserActions(true,true,true,true,true),
|
||||
new UserActions(true,true,true,true,true),
|
||||
new UserActions(true,true,true,true,true),
|
||||
new UserActions(true,true,true,true,true),
|
||||
new UserActions(true,true,true,true,true),
|
||||
new UserActions(true,true,true,true,true),
|
||||
new UserActions(true, true, true, true, true),
|
||||
new UserActions(true, true, true, true, true),
|
||||
new UserActions(true, true, true, true, true),
|
||||
new UserActions(true, true, true, true, true),
|
||||
new UserActions(true, true, true, true, true),
|
||||
new UserActions(true, true, true, true, true),
|
||||
new UserActions(true, true, true, true, true),
|
||||
true
|
||||
));
|
||||
|
||||
@@ -207,6 +220,11 @@ public class DisplayServiceTest
|
||||
// -----------------------------------------------------------
|
||||
// GetByType
|
||||
// -----------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that retrieving display configurations by type returns the associated displays
|
||||
/// from the display repository, ensuring the service correctly resolves configurations and
|
||||
/// their linked displays for the given display type.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetByType_ShouldReturnDisplays()
|
||||
{
|
||||
@@ -226,6 +244,10 @@ public class DisplayServiceTest
|
||||
That(result[0], Is.EqualTo(display));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="DisplayService.GetByType"/> returns an empty collection when no display configurations are found for the specified display type.
|
||||
/// </summary>
|
||||
/// <returns>A task that completes when the assertion confirming the empty result has been executed.</returns>
|
||||
[Test]
|
||||
public async Task GetByType_ShouldReturnEmpty_WhenNoConfigsFound()
|
||||
{
|
||||
@@ -240,6 +262,11 @@ public class DisplayServiceTest
|
||||
// -----------------------------------------------------------
|
||||
// GetByPointOfCare
|
||||
// -----------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Tests that GetByPointOfCare returns the displays associated with the specified point of care.
|
||||
/// </summary>
|
||||
/// <param name="poc">The point of care used to look up associated displays.</param>
|
||||
/// <returns>A task representing the asynchronous test execution.</returns>
|
||||
[Test]
|
||||
public async Task GetByPointOfCare_ShouldReturnDisplays()
|
||||
{
|
||||
@@ -257,11 +284,15 @@ public class DisplayServiceTest
|
||||
// -----------------------------------------------------------
|
||||
// GetByConfigId
|
||||
// -----------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="DisplayService.GetByConfigId"/> returns the displays associated with the specified configuration ID retrieved from the repository.
|
||||
/// </summary>
|
||||
/// <returns>A task that completes when the assertion confirms the returned collection contains the expected number of displays.</returns>
|
||||
[Test]
|
||||
public async Task GetByConfigId_ShouldReturnDisplays()
|
||||
{
|
||||
var cfgId = ObjectId.GenerateNewId();
|
||||
var d = new Display { Id = ObjectId.GenerateNewId(), DisplayConfigId = cfgId, Name = "display1"};
|
||||
var d = new Display { Id = ObjectId.GenerateNewId(), DisplayConfigId = cfgId, Name = "display1" };
|
||||
|
||||
_mockDisplayRepository.Setup(r => r.GetByConfigId(cfgId))
|
||||
.ReturnsAsync([d]);
|
||||
@@ -274,6 +305,9 @@ public class DisplayServiceTest
|
||||
// -----------------------------------------------------------
|
||||
// GetByName
|
||||
// -----------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that the <see cref="DisplayService.GetByName"/> method throws a <see cref="NotFoundException"/> when no display matching the specified name is found in the repository.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void GetByName_ShouldThrow_WhenNotFound()
|
||||
{
|
||||
@@ -287,6 +321,9 @@ public class DisplayServiceTest
|
||||
// -----------------------------------------------------------
|
||||
// GetInfo
|
||||
// -----------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that <c>GetInfo</c> returns a <see cref="Display"/> with its associated <c>PointOfCare</c> entries populated when invoked with the "with POC" flag enabled and a valid display identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetInfo_ShouldReturnDisplayWithPoc()
|
||||
{
|
||||
@@ -309,7 +346,7 @@ public class DisplayServiceTest
|
||||
It.IsAny<TimeSpan?>(),
|
||||
It.IsAny<CancellationToken>()))
|
||||
.Returns((string _, Func<Task<Display?>> factory, TimeSpan? _, CancellationToken _) => factory());
|
||||
|
||||
|
||||
_mockDisplayRepository.Setup(r => r.GetById(id)).ReturnsAsync(display);
|
||||
_mockDisplayConfigService.Setup(s => s.GetById(cfgId))
|
||||
.ReturnsAsync(new DisplayConfig { Id = cfgId });
|
||||
@@ -328,11 +365,14 @@ public class DisplayServiceTest
|
||||
// -----------------------------------------------------------
|
||||
// GetByUnitId
|
||||
// -----------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="IDisplayService.GetByUnitId"/> returns the displays associated with the specified unit identifier when the repository contains matching records.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetByUnitId_ShouldReturnDisplays()
|
||||
{
|
||||
var id = ObjectId.GenerateNewId();
|
||||
var d = new Display { Id = ObjectId.GenerateNewId(), UnitId = id , Name = "display1"};
|
||||
var d = new Display { Id = ObjectId.GenerateNewId(), UnitId = id, Name = "display1" };
|
||||
|
||||
_mockDisplayRepository.Setup(r => r.GetByUnitId(id))
|
||||
.ReturnsAsync([d]);
|
||||
@@ -345,6 +385,10 @@ public class DisplayServiceTest
|
||||
// -----------------------------------------------------------
|
||||
// UpdatePointOfCareList
|
||||
// -----------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that UpdatePointOfCareList throws a <see cref="NotFoundException"/> when the display with the specified identifier does not exist.
|
||||
/// </summary>
|
||||
/// <exception cref="NotFoundException">Thrown when no display is found for the given id.</exception>
|
||||
[Test]
|
||||
public void UpdatePointOfCareList_ShouldThrow_WhenDisplayNotFound()
|
||||
{
|
||||
@@ -360,6 +404,11 @@ public class DisplayServiceTest
|
||||
// -----------------------------------------------------------
|
||||
// UpdateConfigPreset
|
||||
// -----------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="DisplayService.UpdateConfigPreset"/> throws a <see cref="NotFoundException"/> when the repository update operation returns a null result, indicating the display or configuration preset could not be found.
|
||||
/// </summary>
|
||||
/// <param name="id">The unique identifier of the display whose configuration preset is being updated.</param>
|
||||
/// <param name="cfgId">The unique identifier of the configuration preset to associate with the display.</param>
|
||||
[Test]
|
||||
public void UpdateConfigPreset_ShouldThrow_WhenUpdateFails()
|
||||
{
|
||||
|
||||
@@ -15,124 +15,140 @@ namespace adas_core.Test.Services;
|
||||
[TestFixture]
|
||||
public class GroupedObservationServiceTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the test fixture before each test by creating mocked dependencies
|
||||
/// (configuration observation service, observation repository, logger, and cache service)
|
||||
/// and instantiating the <see cref="GroupedObservationService"/> under test with default API and cache settings.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
var configObservationService = new Mock<IConfigObservationService>();
|
||||
var observationRepository = new Mock<IObservationRepository>();
|
||||
|
||||
_logger = new Mock<ILogger<GroupedObservationService>>();
|
||||
|
||||
_groupedObservationService = new GroupedObservationService(
|
||||
observationRepository.Object, configObservationService.Object,
|
||||
_logger.Object, Mock.Of<ICacheService>(), Options.Create(new ApiSettings()), Options.Create(new CacheSettings()));
|
||||
}
|
||||
public void Setup()
|
||||
{
|
||||
var configObservationService = new Mock<IConfigObservationService>();
|
||||
var observationRepository = new Mock<IObservationRepository>();
|
||||
|
||||
_logger = new Mock<ILogger<GroupedObservationService>>();
|
||||
|
||||
_groupedObservationService = new GroupedObservationService(
|
||||
observationRepository.Object, configObservationService.Object,
|
||||
_logger.Object, Mock.Of<ICacheService>(), Options.Create(new ApiSettings()), Options.Create(new CacheSettings()));
|
||||
}
|
||||
|
||||
private GroupedObservationService _groupedObservationService;
|
||||
private Mock<ILogger<GroupedObservationService>> _logger;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Tests that shift observations are correctly generated and grouped by shift time intervals (08:00, 15:00, 22:00) across multiple days,
|
||||
/// verifying the distribution of observations across shifts for the current day, the previous day, and two days prior when the
|
||||
/// Result.Last aggregation is applied with a maximum count of 36.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Generate_Shift_Observations()
|
||||
{
|
||||
var dateTime = DateTime.Now;
|
||||
if (dateTime.Day <= 2) dateTime = dateTime.AddDays(2);
|
||||
|
||||
var result = new List<BsonDocument>
|
||||
public void Generate_Shift_Observations()
|
||||
{
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 12, 30, "FC", 100, Result.Last, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 10, 30, "FC", 108, Result.Last, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 9, 30, "FC", 106, Result.Last, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 5, 30, "FC", 112, Result.Last, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 4, 30, "FC", 105, Result.Last, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day - 1, 23, 30, "FC", 190, Result.Last, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day - 1, 19, 30, "FC", 120, Result.Last, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day - 1, 15, 30, "FC", 130, Result.Last, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day - 1, 12, 30, "FC", 140, Result.Last, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day - 1, 09, 30, "FC", 150, Result.Last, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day - 2, 15, 30, "FC", 150, Result.Last, null)
|
||||
};
|
||||
|
||||
var groupedField = new GroupedField
|
||||
{
|
||||
StartTimeShift = ["08:00", "15:00", "22:00"],
|
||||
Max = 36,
|
||||
Result = [Result.Last]
|
||||
};
|
||||
|
||||
var shiftObservations = _groupedObservationService.GenerateShiftObservations(result, groupedField);
|
||||
|
||||
var shift1ObsToday = shiftObservations.Count(s => s.Get("shift") == 0 && s.Get("day") == dateTime.Day);
|
||||
|
||||
var shift1ObsYesterday = shiftObservations.Count(s => s.Get("shift") == 0 && s.Get("day") == dateTime.Day - 1);
|
||||
|
||||
var shift2ObsYesterday = shiftObservations.Count(s => s.Get("shift") == 1 && s.Get("day") == dateTime.Day - 1);
|
||||
|
||||
var shif3ObsYesterday = shiftObservations.Count(s => s.Get("shift") == 2 && s.Get("day") == dateTime.Day - 1);
|
||||
|
||||
var shiftTwoDaysAgo = shiftObservations.Count(s => s.Get("shift") == 1 && s.Get("day") == dateTime.Day - 2);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(shift1ObsToday, Is.EqualTo(3));
|
||||
Assert.That(shif3ObsYesterday, Is.EqualTo(3));
|
||||
Assert.That(shift2ObsYesterday, Is.EqualTo(2));
|
||||
Assert.That(shift1ObsYesterday, Is.EqualTo(2));
|
||||
Assert.That(shiftTwoDaysAgo, Is.EqualTo(1));
|
||||
};
|
||||
}
|
||||
var dateTime = DateTime.Now;
|
||||
if (dateTime.Day <= 2) dateTime = dateTime.AddDays(2);
|
||||
|
||||
var result = new List<BsonDocument>
|
||||
{
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 12, 30, "FC", 100, Result.Last, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 10, 30, "FC", 108, Result.Last, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 9, 30, "FC", 106, Result.Last, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 5, 30, "FC", 112, Result.Last, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 4, 30, "FC", 105, Result.Last, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day - 1, 23, 30, "FC", 190, Result.Last, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day - 1, 19, 30, "FC", 120, Result.Last, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day - 1, 15, 30, "FC", 130, Result.Last, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day - 1, 12, 30, "FC", 140, Result.Last, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day - 1, 09, 30, "FC", 150, Result.Last, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day - 2, 15, 30, "FC", 150, Result.Last, null)
|
||||
};
|
||||
|
||||
var groupedField = new GroupedField
|
||||
{
|
||||
StartTimeShift = ["08:00", "15:00", "22:00"],
|
||||
Max = 36,
|
||||
Result = [Result.Last]
|
||||
};
|
||||
|
||||
var shiftObservations = _groupedObservationService.GenerateShiftObservations(result, groupedField);
|
||||
|
||||
var shift1ObsToday = shiftObservations.Count(s => s.Get("shift") == 0 && s.Get("day") == dateTime.Day);
|
||||
|
||||
var shift1ObsYesterday = shiftObservations.Count(s => s.Get("shift") == 0 && s.Get("day") == dateTime.Day - 1);
|
||||
|
||||
var shift2ObsYesterday = shiftObservations.Count(s => s.Get("shift") == 1 && s.Get("day") == dateTime.Day - 1);
|
||||
|
||||
var shif3ObsYesterday = shiftObservations.Count(s => s.Get("shift") == 2 && s.Get("day") == dateTime.Day - 1);
|
||||
|
||||
var shiftTwoDaysAgo = shiftObservations.Count(s => s.Get("shift") == 1 && s.Get("day") == dateTime.Day - 2);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(shift1ObsToday, Is.EqualTo(3));
|
||||
Assert.That(shif3ObsYesterday, Is.EqualTo(3));
|
||||
Assert.That(shift2ObsYesterday, Is.EqualTo(2));
|
||||
Assert.That(shift1ObsYesterday, Is.EqualTo(2));
|
||||
Assert.That(shiftTwoDaysAgo, Is.EqualTo(1));
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the grouped observation service correctly calculates sum values for shift observations
|
||||
/// across multiple days and shift periods (08:00, 15:00, 22:00), including observations that fall within
|
||||
/// the current day, the previous day, and two days prior, ensuring that data is aggregated into the
|
||||
/// correct shift and day buckets.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Calculate_Shift_Observations()
|
||||
{
|
||||
var dateTime = DateTime.Now;
|
||||
|
||||
if (dateTime.Day <= 2) dateTime = dateTime.AddDays(2);
|
||||
|
||||
|
||||
var groupedField = new GroupedField
|
||||
public void Calculate_Shift_Observations()
|
||||
{
|
||||
StartTimeShift = ["08:00", "15:00", "22:00"],
|
||||
Max = 36,
|
||||
Result = [Result.Sum]
|
||||
};
|
||||
|
||||
var result = new List<BsonDocument>
|
||||
{
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 12, 30, "FC", 100, Result.Sum, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 10, 30, "FC", 108, Result.Sum, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 9, 30, "FC", 106, Result.Sum, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 5, 30, "FC", 112, Result.Sum, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 4, 30, "FC", 105, Result.Sum, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day - 1, 23, 30, "FC", 190, Result.Sum, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day - 1, 19, 30, "FC", 120, Result.Sum, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day - 1, 15, 30, "FC", 130, Result.Sum, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day - 1, 12, 30, "FC", 140, Result.Sum, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day - 1, 09, 30, "FC", 150, Result.Sum, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day - 2, 15, 30, "FC", 150, Result.Sum, null)
|
||||
};
|
||||
|
||||
|
||||
var shiftObservations = _groupedObservationService.GenerateShiftObservations(result, groupedField);
|
||||
|
||||
_groupedObservationService.CalculateShiftObservations(shiftObservations, groupedField);
|
||||
var shift1ObsToday = shiftObservations.First(s => s.Get("shift") == 0 && s.Get("day") == dateTime.Day);
|
||||
var shift1ObsYesterday = shiftObservations.First(s => s.Get("shift") == 0 && s.Get("day") == dateTime.Day - 1);
|
||||
|
||||
var shift2ObsYesterday = shiftObservations.First(s => s.Get("shift") == 1 && s.Get("day") == dateTime.Day - 1);
|
||||
|
||||
var shif3ObsYesterday = shiftObservations.First(s => s.Get("shift") == 2 && s.Get("day") == dateTime.Day - 1);
|
||||
|
||||
var shiftTwoDaysAgo = shiftObservations.First(s => s.Get("shift") == 1 && s.Get("day") == dateTime.Day - 2);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(shift1ObsToday.Get("sum")?.ToInt32(), Is.EqualTo(314));
|
||||
Assert.That(shif3ObsYesterday.Get("sum")?.ToInt32(), Is.EqualTo(407));
|
||||
|
||||
Assert.That(shift2ObsYesterday.Get("sum")?.ToInt32(), Is.EqualTo(250));
|
||||
Assert.That(shift1ObsYesterday.Get("sum")?.ToInt32(), Is.EqualTo(290));
|
||||
Assert.That(shiftTwoDaysAgo.Get("sum")?.ToInt32(), Is.EqualTo(150));
|
||||
};
|
||||
}
|
||||
var dateTime = DateTime.Now;
|
||||
|
||||
if (dateTime.Day <= 2) dateTime = dateTime.AddDays(2);
|
||||
|
||||
|
||||
var groupedField = new GroupedField
|
||||
{
|
||||
StartTimeShift = ["08:00", "15:00", "22:00"],
|
||||
Max = 36,
|
||||
Result = [Result.Sum]
|
||||
};
|
||||
|
||||
var result = new List<BsonDocument>
|
||||
{
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 12, 30, "FC", 100, Result.Sum, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 10, 30, "FC", 108, Result.Sum, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 9, 30, "FC", 106, Result.Sum, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 5, 30, "FC", 112, Result.Sum, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 4, 30, "FC", 105, Result.Sum, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day - 1, 23, 30, "FC", 190, Result.Sum, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day - 1, 19, 30, "FC", 120, Result.Sum, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day - 1, 15, 30, "FC", 130, Result.Sum, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day - 1, 12, 30, "FC", 140, Result.Sum, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day - 1, 09, 30, "FC", 150, Result.Sum, null),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day - 2, 15, 30, "FC", 150, Result.Sum, null)
|
||||
};
|
||||
|
||||
|
||||
var shiftObservations = _groupedObservationService.GenerateShiftObservations(result, groupedField);
|
||||
|
||||
_groupedObservationService.CalculateShiftObservations(shiftObservations, groupedField);
|
||||
var shift1ObsToday = shiftObservations.First(s => s.Get("shift") == 0 && s.Get("day") == dateTime.Day);
|
||||
var shift1ObsYesterday = shiftObservations.First(s => s.Get("shift") == 0 && s.Get("day") == dateTime.Day - 1);
|
||||
|
||||
var shift2ObsYesterday = shiftObservations.First(s => s.Get("shift") == 1 && s.Get("day") == dateTime.Day - 1);
|
||||
|
||||
var shif3ObsYesterday = shiftObservations.First(s => s.Get("shift") == 2 && s.Get("day") == dateTime.Day - 1);
|
||||
|
||||
var shiftTwoDaysAgo = shiftObservations.First(s => s.Get("shift") == 1 && s.Get("day") == dateTime.Day - 2);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(shift1ObsToday.Get("sum")?.ToInt32(), Is.EqualTo(314));
|
||||
Assert.That(shif3ObsYesterday.Get("sum")?.ToInt32(), Is.EqualTo(407));
|
||||
|
||||
Assert.That(shift2ObsYesterday.Get("sum")?.ToInt32(), Is.EqualTo(250));
|
||||
Assert.That(shift1ObsYesterday.Get("sum")?.ToInt32(), Is.EqualTo(290));
|
||||
Assert.That(shiftTwoDaysAgo.Get("sum")?.ToInt32(), Is.EqualTo(150));
|
||||
};
|
||||
}
|
||||
|
||||
// [Test]
|
||||
// public void Calculate_Half_Time_Observations()
|
||||
@@ -223,265 +239,291 @@ public class GroupedObservationServiceTest
|
||||
// });
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>CalculateLastFilledObservations</c> fills the missing hourly slot at <c>now - 4 hours</c>
|
||||
/// so that the returned sequence contains a complete set of five consecutive hourly observations
|
||||
/// (covering the last five hours relative to the current time) for a group with hourly regularity and a maximum of five entries.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Calculate_Last_Filled_Observations_should_add_Minus_4_hour_to_complete_last_five_hours()
|
||||
{
|
||||
var dateTime = DateTime.Now;
|
||||
|
||||
//Falta el -4 tiene que crearlo el calculate last filled observation
|
||||
var result = new List<BsonDocument>
|
||||
public async Task Calculate_Last_Filled_Observations_should_add_Minus_4_hour_to_complete_last_five_hours()
|
||||
{
|
||||
GenerateBsonDocument(dateTime.AddHours(-5).Year, dateTime.AddHours(-5).Month, dateTime.AddHours(-5).Day,
|
||||
dateTime.AddHours(-5).Hour, 0, "TAM", 100, Result.LastFilled, null),
|
||||
GenerateBsonDocument(dateTime.AddHours(-3).Year, dateTime.AddHours(-3).Month, dateTime.AddHours(-3).Day,
|
||||
dateTime.AddHours(-3).Hour, 0, "TAM", 100, Result.LastFilled, null),
|
||||
GenerateBsonDocument(dateTime.AddHours(-2).Year, dateTime.AddHours(-2).Month, dateTime.AddHours(-2).Day,
|
||||
dateTime.AddHours(-2).Hour, 0, "TAM", 100, Result.LastFilled, null),
|
||||
GenerateBsonDocument(dateTime.AddHours(-1).Year, dateTime.AddHours(-1).Month, dateTime.AddHours(-1).Day,
|
||||
dateTime.AddHours(-1).Hour, 0, "TAM", 100, Result.LastFilled, null)
|
||||
};
|
||||
|
||||
|
||||
var groupedField = new GroupedField
|
||||
{
|
||||
Max = 5,
|
||||
Name = "TAM",
|
||||
Regularity = Regularity.Hour
|
||||
};
|
||||
var patientId = ObjectId.GenerateNewId();
|
||||
|
||||
var lastFilledObservations =
|
||||
await _groupedObservationService.CalculateLastFilledObservations(result, groupedField, patientId);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(lastFilledObservations, Has.Count.EqualTo(5));
|
||||
Assert.That(
|
||||
lastFilledObservations.Exists(i => i.Get("time")?.ToLocalTime().Hour == dateTime.AddHours(-5).Hour),
|
||||
Is.True);
|
||||
Assert.That(
|
||||
lastFilledObservations.Exists(i => i.Get("time")?.ToLocalTime().Hour == dateTime.AddHours(-4).Hour),
|
||||
Is.True);
|
||||
Assert.That(
|
||||
lastFilledObservations.Exists(i => i.Get("time")?.ToLocalTime().Hour == dateTime.AddHours(-3).Hour),
|
||||
Is.True);
|
||||
Assert.That(
|
||||
lastFilledObservations.Exists(i => i.Get("time")?.ToLocalTime().Hour == dateTime.AddHours(-2).Hour),
|
||||
Is.True);
|
||||
Assert.That(
|
||||
lastFilledObservations.Exists(i => i.Get("time")?.ToLocalTime().Hour == dateTime.AddHours(-1).Hour),
|
||||
Is.True);
|
||||
};
|
||||
}
|
||||
var dateTime = DateTime.Now;
|
||||
|
||||
//Falta el -4 tiene que crearlo el calculate last filled observation
|
||||
var result = new List<BsonDocument>
|
||||
{
|
||||
GenerateBsonDocument(dateTime.AddHours(-5).Year, dateTime.AddHours(-5).Month, dateTime.AddHours(-5).Day,
|
||||
dateTime.AddHours(-5).Hour, 0, "TAM", 100, Result.LastFilled, null),
|
||||
GenerateBsonDocument(dateTime.AddHours(-3).Year, dateTime.AddHours(-3).Month, dateTime.AddHours(-3).Day,
|
||||
dateTime.AddHours(-3).Hour, 0, "TAM", 100, Result.LastFilled, null),
|
||||
GenerateBsonDocument(dateTime.AddHours(-2).Year, dateTime.AddHours(-2).Month, dateTime.AddHours(-2).Day,
|
||||
dateTime.AddHours(-2).Hour, 0, "TAM", 100, Result.LastFilled, null),
|
||||
GenerateBsonDocument(dateTime.AddHours(-1).Year, dateTime.AddHours(-1).Month, dateTime.AddHours(-1).Day,
|
||||
dateTime.AddHours(-1).Hour, 0, "TAM", 100, Result.LastFilled, null)
|
||||
};
|
||||
|
||||
|
||||
var groupedField = new GroupedField
|
||||
{
|
||||
Max = 5,
|
||||
Name = "TAM",
|
||||
Regularity = Regularity.Hour
|
||||
};
|
||||
var patientId = ObjectId.GenerateNewId();
|
||||
|
||||
var lastFilledObservations =
|
||||
await _groupedObservationService.CalculateLastFilledObservations(result, groupedField, patientId);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(lastFilledObservations, Has.Count.EqualTo(5));
|
||||
Assert.That(
|
||||
lastFilledObservations.Exists(i => i.Get("time")?.ToLocalTime().Hour == dateTime.AddHours(-5).Hour),
|
||||
Is.True);
|
||||
Assert.That(
|
||||
lastFilledObservations.Exists(i => i.Get("time")?.ToLocalTime().Hour == dateTime.AddHours(-4).Hour),
|
||||
Is.True);
|
||||
Assert.That(
|
||||
lastFilledObservations.Exists(i => i.Get("time")?.ToLocalTime().Hour == dateTime.AddHours(-3).Hour),
|
||||
Is.True);
|
||||
Assert.That(
|
||||
lastFilledObservations.Exists(i => i.Get("time")?.ToLocalTime().Hour == dateTime.AddHours(-2).Hour),
|
||||
Is.True);
|
||||
Assert.That(
|
||||
lastFilledObservations.Exists(i => i.Get("time")?.ToLocalTime().Hour == dateTime.AddHours(-1).Hour),
|
||||
Is.True);
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>CalculateLastFilledObservations</c> fills missing hourly entries in the last five hours,
|
||||
/// adding the <c>-1 hour</c> observation when it is not present in the provided list so that the returned
|
||||
/// collection always contains a complete five-hour window of last filled observations.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Calculate_Last_Filled_Observations_should_add_Minus_1_hour_to_complete_last_five_hours()
|
||||
{
|
||||
var dateTime = DateTime.Now;
|
||||
|
||||
//Falta el -4 tiene que crearlo el calculate last filled observation
|
||||
var result = new List<BsonDocument>
|
||||
public async Task Calculate_Last_Filled_Observations_should_add_Minus_1_hour_to_complete_last_five_hours()
|
||||
{
|
||||
GenerateBsonDocument(dateTime.AddHours(-5).Year, dateTime.AddHours(-5).Month, dateTime.AddHours(-5).Day,
|
||||
dateTime.AddHours(-5).Hour, 0, "TAM", 100, Result.LastFilled, null),
|
||||
GenerateBsonDocument(dateTime.AddHours(-4).Year, dateTime.AddHours(-4).Month, dateTime.AddHours(-4).Day,
|
||||
dateTime.AddHours(-4).Hour, 0, "TAM", 100, Result.LastFilled, null),
|
||||
GenerateBsonDocument(dateTime.AddHours(-3).Year, dateTime.AddHours(-3).Month, dateTime.AddHours(-3).Day,
|
||||
dateTime.AddHours(-3).Hour, 0, "TAM", 100, Result.LastFilled, null),
|
||||
GenerateBsonDocument(dateTime.AddHours(-2).Year, dateTime.AddHours(-2).Month, dateTime.AddHours(-2).Day,
|
||||
dateTime.AddHours(-2).Hour, 0, "TAM", 100, Result.LastFilled, null)
|
||||
};
|
||||
|
||||
|
||||
var groupedField = new GroupedField
|
||||
{
|
||||
Max = 5,
|
||||
Name = "TAM",
|
||||
Regularity = Regularity.Hour
|
||||
};
|
||||
var patientId = ObjectId.GenerateNewId();
|
||||
|
||||
var lastFilledObservations =
|
||||
await _groupedObservationService.CalculateLastFilledObservations(result, groupedField, patientId);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(lastFilledObservations, Has.Count.EqualTo(5));
|
||||
Assert.That(
|
||||
lastFilledObservations.Exists(i => i.Get("time")?.ToLocalTime().Hour == dateTime.AddHours(-5).Hour),
|
||||
Is.True);
|
||||
Assert.That(
|
||||
lastFilledObservations.Exists(i => i.Get("time")?.ToLocalTime().Hour == dateTime.AddHours(-4).Hour),
|
||||
Is.True);
|
||||
Assert.That(
|
||||
lastFilledObservations.Exists(i => i.Get("time")?.ToLocalTime().Hour == dateTime.AddHours(-3).Hour),
|
||||
Is.True);
|
||||
Assert.That(
|
||||
lastFilledObservations.Exists(i => i.Get("time")?.ToLocalTime().Hour == dateTime.AddHours(-2).Hour),
|
||||
Is.True);
|
||||
Assert.That(
|
||||
lastFilledObservations.Exists(i => i.Get("time")?.ToLocalTime().Hour == dateTime.AddHours(-1).Hour),
|
||||
Is.True);
|
||||
};
|
||||
}
|
||||
var dateTime = DateTime.Now;
|
||||
|
||||
//Falta el -4 tiene que crearlo el calculate last filled observation
|
||||
var result = new List<BsonDocument>
|
||||
{
|
||||
GenerateBsonDocument(dateTime.AddHours(-5).Year, dateTime.AddHours(-5).Month, dateTime.AddHours(-5).Day,
|
||||
dateTime.AddHours(-5).Hour, 0, "TAM", 100, Result.LastFilled, null),
|
||||
GenerateBsonDocument(dateTime.AddHours(-4).Year, dateTime.AddHours(-4).Month, dateTime.AddHours(-4).Day,
|
||||
dateTime.AddHours(-4).Hour, 0, "TAM", 100, Result.LastFilled, null),
|
||||
GenerateBsonDocument(dateTime.AddHours(-3).Year, dateTime.AddHours(-3).Month, dateTime.AddHours(-3).Day,
|
||||
dateTime.AddHours(-3).Hour, 0, "TAM", 100, Result.LastFilled, null),
|
||||
GenerateBsonDocument(dateTime.AddHours(-2).Year, dateTime.AddHours(-2).Month, dateTime.AddHours(-2).Day,
|
||||
dateTime.AddHours(-2).Hour, 0, "TAM", 100, Result.LastFilled, null)
|
||||
};
|
||||
|
||||
|
||||
var groupedField = new GroupedField
|
||||
{
|
||||
Max = 5,
|
||||
Name = "TAM",
|
||||
Regularity = Regularity.Hour
|
||||
};
|
||||
var patientId = ObjectId.GenerateNewId();
|
||||
|
||||
var lastFilledObservations =
|
||||
await _groupedObservationService.CalculateLastFilledObservations(result, groupedField, patientId);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(lastFilledObservations, Has.Count.EqualTo(5));
|
||||
Assert.That(
|
||||
lastFilledObservations.Exists(i => i.Get("time")?.ToLocalTime().Hour == dateTime.AddHours(-5).Hour),
|
||||
Is.True);
|
||||
Assert.That(
|
||||
lastFilledObservations.Exists(i => i.Get("time")?.ToLocalTime().Hour == dateTime.AddHours(-4).Hour),
|
||||
Is.True);
|
||||
Assert.That(
|
||||
lastFilledObservations.Exists(i => i.Get("time")?.ToLocalTime().Hour == dateTime.AddHours(-3).Hour),
|
||||
Is.True);
|
||||
Assert.That(
|
||||
lastFilledObservations.Exists(i => i.Get("time")?.ToLocalTime().Hour == dateTime.AddHours(-2).Hour),
|
||||
Is.True);
|
||||
Assert.That(
|
||||
lastFilledObservations.Exists(i => i.Get("time")?.ToLocalTime().Hour == dateTime.AddHours(-1).Hour),
|
||||
Is.True);
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the service correctly fills hourly observations from half-hour observation data, grouping timestamped values by hour and forwarding missing slots up to the configured maximum (5) per hour.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void FillHoursObservations()
|
||||
{
|
||||
/*
|
||||
09:18 - Toma 1: 50/100/75
|
||||
09:38 - Toma 2: 52/102/76
|
||||
10:07 - Toma 3: 54/101/72
|
||||
10:18 - Toma 4: 51/102/73
|
||||
10:58 - Toma 5: 52/107/79
|
||||
12:04 - Toma 6: 60/120/90
|
||||
|
||||
El api convierte a
|
||||
|
||||
09h - Toma 2: 52/102/76
|
||||
10h - Toma 4: 51/102/73
|
||||
11h - Toma 5: 52/107/79
|
||||
12h- Toma 6: 60/120/90
|
||||
*/
|
||||
|
||||
var groupedField = new GroupedField
|
||||
public void FillHoursObservations()
|
||||
{
|
||||
Max = 5,
|
||||
Name = "TAM",
|
||||
Regularity = Regularity.Hour
|
||||
};
|
||||
|
||||
|
||||
var dateTime =
|
||||
new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 12, 30, 0).ToUniversalTime();
|
||||
|
||||
var values9 = new BsonArray
|
||||
{
|
||||
new BsonDocument
|
||||
/*
|
||||
09:18 - Toma 1: 50/100/75
|
||||
09:38 - Toma 2: 52/102/76
|
||||
10:07 - Toma 3: 54/101/72
|
||||
10:18 - Toma 4: 51/102/73
|
||||
10:58 - Toma 5: 52/107/79
|
||||
12:04 - Toma 6: 60/120/90
|
||||
|
||||
El api convierte a
|
||||
|
||||
09h - Toma 2: 52/102/76
|
||||
10h - Toma 4: 51/102/73
|
||||
11h - Toma 5: 52/107/79
|
||||
12h- Toma 6: 60/120/90
|
||||
*/
|
||||
|
||||
var groupedField = new GroupedField
|
||||
{
|
||||
{ "value", 50 },
|
||||
{
|
||||
"time",
|
||||
new BsonDateTime(
|
||||
new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 9, 18, 0).ToUniversalTime())
|
||||
}
|
||||
},
|
||||
new BsonDocument
|
||||
Max = 5,
|
||||
Name = "TAM",
|
||||
Regularity = Regularity.Hour
|
||||
};
|
||||
|
||||
|
||||
var dateTime =
|
||||
new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 12, 30, 0).ToUniversalTime();
|
||||
|
||||
var values9 = new BsonArray
|
||||
{
|
||||
{ "value", 100 },
|
||||
new BsonDocument
|
||||
{
|
||||
"time",
|
||||
new BsonDateTime(
|
||||
new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 9, 38, 0).ToUniversalTime())
|
||||
{ "value", 50 },
|
||||
{
|
||||
"time",
|
||||
new BsonDateTime(
|
||||
new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 9, 18, 0).ToUniversalTime())
|
||||
}
|
||||
},
|
||||
new BsonDocument
|
||||
{
|
||||
{ "value", 100 },
|
||||
{
|
||||
"time",
|
||||
new BsonDateTime(
|
||||
new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 9, 38, 0).ToUniversalTime())
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var values10 = new BsonArray
|
||||
{
|
||||
new BsonDocument
|
||||
};
|
||||
|
||||
var values10 = new BsonArray
|
||||
{
|
||||
{ "value", 50 },
|
||||
new BsonDocument
|
||||
{
|
||||
"time",
|
||||
new BsonDateTime(
|
||||
new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 10, 7, 0).ToUniversalTime())
|
||||
{ "value", 50 },
|
||||
{
|
||||
"time",
|
||||
new BsonDateTime(
|
||||
new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 10, 7, 0).ToUniversalTime())
|
||||
}
|
||||
},
|
||||
new BsonDocument
|
||||
{
|
||||
{ "value", 60 },
|
||||
{
|
||||
"time",
|
||||
new BsonDateTime(new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 10, 18, 0)
|
||||
.ToUniversalTime())
|
||||
}
|
||||
},
|
||||
new BsonDocument
|
||||
{
|
||||
{ "value", 70 },
|
||||
{
|
||||
"time",
|
||||
new BsonDateTime(new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 10, 58, 0)
|
||||
.ToUniversalTime())
|
||||
}
|
||||
}
|
||||
},
|
||||
new BsonDocument
|
||||
};
|
||||
|
||||
var values12 = new BsonArray
|
||||
{
|
||||
{ "value", 60 },
|
||||
new BsonDocument
|
||||
{
|
||||
"time",
|
||||
new BsonDateTime(new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 10, 18, 0)
|
||||
.ToUniversalTime())
|
||||
{ "value", 50 },
|
||||
{
|
||||
"time",
|
||||
new BsonDateTime(new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 12, 04, 0)
|
||||
.ToUniversalTime())
|
||||
}
|
||||
}
|
||||
},
|
||||
new BsonDocument
|
||||
};
|
||||
|
||||
|
||||
var result = new List<BsonDocument>
|
||||
{
|
||||
{ "value", 70 },
|
||||
{
|
||||
"time",
|
||||
new BsonDateTime(new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 10, 58, 0)
|
||||
.ToUniversalTime())
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var values12 = new BsonArray
|
||||
{
|
||||
new BsonDocument
|
||||
{
|
||||
{ "value", 50 },
|
||||
{
|
||||
"time",
|
||||
new BsonDateTime(new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 12, 04, 0)
|
||||
.ToUniversalTime())
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var result = new List<BsonDocument>
|
||||
{
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 9, 0, "TAM", 100, Result.HalfHour,
|
||||
values9),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 10, 0, "TAM", 100, Result.HalfHour,
|
||||
values10),
|
||||
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 12, 0, "TAM", 100, Result.HalfHour,
|
||||
values12)
|
||||
};
|
||||
|
||||
var halfObservations = _groupedObservationService.CalculateHalfHourObservations(result);
|
||||
|
||||
var fillHoursObservations = _groupedObservationService.FillHours(halfObservations, groupedField);
|
||||
|
||||
|
||||
Assert.That(fillHoursObservations, Is.Not.Empty);
|
||||
}
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 9, 0, "TAM", 100, Result.HalfHour,
|
||||
values9),
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 10, 0, "TAM", 100, Result.HalfHour,
|
||||
values10),
|
||||
|
||||
GenerateBsonDocument(dateTime.Year, dateTime.Month, dateTime.Day, 12, 0, "TAM", 100, Result.HalfHour,
|
||||
values12)
|
||||
};
|
||||
|
||||
var halfObservations = _groupedObservationService.CalculateHalfHourObservations(result);
|
||||
|
||||
var fillHoursObservations = _groupedObservationService.FillHours(halfObservations, groupedField);
|
||||
|
||||
|
||||
Assert.That(fillHoursObservations, Is.Not.Empty);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Generates a BsonDocument representing a time-stamped result entry, with date component fallbacks to the current date when null and conditional payload structure based on the result type.
|
||||
/// </summary>
|
||||
/// <param name="year">The year component of the entry timestamp, or null to default to the current year.</param>
|
||||
/// <param name="month">The month component of the entry timestamp, or null to default to the current month.</param>
|
||||
/// <param name="day">The day component of the entry timestamp, or null to default to the current day.</param>
|
||||
/// <param name="hour">The hour component of the entry timestamp, or null to default to the current hour.</param>
|
||||
/// <param name="minute">The minute component of the entry timestamp, or null to default to the current minute.</param>
|
||||
/// <param name="name">The name identifier included in the document's _id.</param>
|
||||
/// <param name="value">The raw value associated with the result.</param>
|
||||
/// <param name="resultType">The result type that determines how the value is stored; aggregate types (HalfHour, Sum, Count, Min, Average, Max) are stored directly, while others are wrapped in a sub-document with time and stringified value.</param>
|
||||
/// <param name="all">Optional BsonArray of additional entries; when provided, it is appended to the result under the "all" key.</param>
|
||||
/// <returns>A BsonDocument containing the _id composite key, a time field, the result-type-specific payload, and optionally the "all" array.</returns>
|
||||
private static BsonDocument GenerateBsonDocument(int? year, int? month, int? day, int? hour, int? minute,
|
||||
string name, object value, Result resultType, BsonArray? all)
|
||||
{
|
||||
var result = new BsonDocument
|
||||
string name, object value, Result resultType, BsonArray? all)
|
||||
{
|
||||
var result = new BsonDocument
|
||||
{
|
||||
"_id", new BsonDocument
|
||||
{
|
||||
{ "year", year ?? new DateTime().Year },
|
||||
{ "month", month ?? new DateTime().Month },
|
||||
{ "day", day ?? new DateTime().Day },
|
||||
{ "hour", hour ?? new DateTime().Hour },
|
||||
{ "minute", minute ?? new DateTime().Minute },
|
||||
{ "name", name }
|
||||
}
|
||||
},
|
||||
{ "time", new BsonDateTime(new DateTime((int)year!, (int)month!, (int)day!, (int)hour!, (int)minute!, 0)) }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
{resultType.ToString().ToLower(), new BsonDocument{
|
||||
{"time", new BsonDateTime(new System.DateTime((int)year, (int)month, (int)day, (int)hour, (int)minute,0)) },
|
||||
{"value", value.ToString() }
|
||||
}},
|
||||
{ "time", new BsonDateTime(new System.DateTime((int)year, (int)month, (int)day, (int)hour, (int)minute,0)) },
|
||||
|
||||
};
|
||||
*/
|
||||
|
||||
if (resultType != Result.HalfHour && resultType != Result.Sum && resultType != Result.Count
|
||||
&& resultType != Result.Min && resultType != Result.Average && resultType != Result.Max)
|
||||
result.Add(resultType.ToString().ToLower(), new BsonDocument
|
||||
{
|
||||
{ "time", new BsonDateTime(new DateTime((int)year, (int)month, (int)day, (int)hour, (int)minute, 0)) },
|
||||
{ "value", value.ToString() }
|
||||
});
|
||||
else
|
||||
result.AddRange(new Dictionary<string, object> { { resultType.ToString().ToLower(), value } });
|
||||
|
||||
if (all != null) result.Add("all", all);
|
||||
|
||||
return result;
|
||||
}
|
||||
"_id", new BsonDocument
|
||||
{
|
||||
{ "year", year ?? new DateTime().Year },
|
||||
{ "month", month ?? new DateTime().Month },
|
||||
{ "day", day ?? new DateTime().Day },
|
||||
{ "hour", hour ?? new DateTime().Hour },
|
||||
{ "minute", minute ?? new DateTime().Minute },
|
||||
{ "name", name }
|
||||
}
|
||||
},
|
||||
{ "time", new BsonDateTime(new DateTime((int)year!, (int)month!, (int)day!, (int)hour!, (int)minute!, 0)) }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
{resultType.ToString().ToLower(), new BsonDocument{
|
||||
{"time", new BsonDateTime(new System.DateTime((int)year, (int)month, (int)day, (int)hour, (int)minute,0)) },
|
||||
{"value", value.ToString() }
|
||||
}},
|
||||
{ "time", new BsonDateTime(new System.DateTime((int)year, (int)month, (int)day, (int)hour, (int)minute,0)) },
|
||||
|
||||
};
|
||||
*/
|
||||
|
||||
if (resultType != Result.HalfHour && resultType != Result.Sum && resultType != Result.Count
|
||||
&& resultType != Result.Min && resultType != Result.Average && resultType != Result.Max)
|
||||
result.Add(resultType.ToString().ToLower(), new BsonDocument
|
||||
{
|
||||
{ "time", new BsonDateTime(new DateTime((int)year, (int)month, (int)day, (int)hour, (int)minute, 0)) },
|
||||
{ "value", value.ToString() }
|
||||
});
|
||||
else
|
||||
result.AddRange(new Dictionary<string, object> { { resultType.ToString().ToLower(), value } });
|
||||
|
||||
if (all != null) result.Add("all", all);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -13,14 +13,17 @@ namespace adas_core.Test.Services;
|
||||
[NonParallelizable]
|
||||
internal class HistoricalConfigChangesServiceTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the mock repository, mock logger, and the <see cref="HistoricalConfigChangesService"/> instance under test prior to each unit test execution.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_mockRepo = new Mock<IHistoricalConfigChangesRepository>();
|
||||
_mockLogger = new Mock<ILogger<HistoricalConfigChangesService>>();
|
||||
_service = new HistoricalConfigChangesService(_mockRepo.Object, _mockLogger.Object, _httpContextAccessor.Object,
|
||||
_auditService.Object);
|
||||
}
|
||||
public void Setup()
|
||||
{
|
||||
_mockRepo = new Mock<IHistoricalConfigChangesRepository>();
|
||||
_mockLogger = new Mock<ILogger<HistoricalConfigChangesService>>();
|
||||
_service = new HistoricalConfigChangesService(_mockRepo.Object, _mockLogger.Object, _httpContextAccessor.Object,
|
||||
_auditService.Object);
|
||||
}
|
||||
|
||||
private HistoricalConfigChangesService _service;
|
||||
private Mock<IHistoricalConfigChangesRepository> _mockRepo;
|
||||
@@ -29,108 +32,129 @@ internal class HistoricalConfigChangesServiceTest
|
||||
private readonly Mock<ILocalAuditService> _auditService = new();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="FindLastConfigChanges"/> returns the last configuration change retrieved from the repository for the specified configuration type.
|
||||
/// </summary>
|
||||
/// <param name="configType">The type of configuration whose last historical changes are being retrieved.</param>
|
||||
/// <returns>A task that represents the asynchronous test execution.</returns>
|
||||
[Test]
|
||||
public async Task FindLastConfigChanges_ReturnsLastConfigChange()
|
||||
{
|
||||
// Arrange
|
||||
var configType = DisplayConfigEnums.ConfigTypes.ObservationCfg;
|
||||
var mockResult = new List<HistoricalConfigChanges>
|
||||
public async Task FindLastConfigChanges_ReturnsLastConfigChange()
|
||||
{
|
||||
new() // Mock object with desired properties
|
||||
};
|
||||
_mockRepo.Setup(r => r.FindLastHistoricalConfigChangesByType(configType, 10)).ReturnsAsync(mockResult);
|
||||
|
||||
// Act
|
||||
var result = await _service.FindLastConfigChanges(configType);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
// Further assertions based on the expected result
|
||||
}
|
||||
// Arrange
|
||||
var configType = DisplayConfigEnums.ConfigTypes.ObservationCfg;
|
||||
var mockResult = new List<HistoricalConfigChanges>
|
||||
{
|
||||
new() // Mock object with desired properties
|
||||
};
|
||||
_mockRepo.Setup(r => r.FindLastHistoricalConfigChangesByType(configType, 10)).ReturnsAsync(mockResult);
|
||||
|
||||
// Act
|
||||
var result = await _service.FindLastConfigChanges(configType);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
// Further assertions based on the expected result
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the service returns <c>null</c> when the underlying repository throws an exception while inserting a <see cref="HistoricalConfigChanges"/> entity.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task InsertOne_WhenExceptionOccurs_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
var mockChange = new HistoricalConfigChanges();
|
||||
_mockRepo.Setup(r => r.InsertOneAsync(mockChange)).Throws(new Exception());
|
||||
|
||||
// Act
|
||||
var result = await _service.InsertOne(mockChange);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public async Task GetAll_ReturnsAllConfigChanges()
|
||||
{
|
||||
// Arrange
|
||||
var mockResult = new List<HistoricalConfigChanges>
|
||||
public async Task InsertOne_WhenExceptionOccurs_ReturnsNull()
|
||||
{
|
||||
new(),
|
||||
new()
|
||||
};
|
||||
_mockRepo.Setup(r => r.FindAll()).ReturnsAsync(mockResult);
|
||||
// Arrange
|
||||
var mockChange = new HistoricalConfigChanges();
|
||||
_mockRepo.Setup(r => r.InsertOneAsync(mockChange)).Throws(new Exception());
|
||||
|
||||
// Act
|
||||
var result = await _service.InsertOne(mockChange);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
// Act
|
||||
var result = await _service.GetAll();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Has.Count.EqualTo(2));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the service's <c>GetAll</c> method returns all historical configuration changes retrieved from the repository.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetByType_ReturnsCorrectAmountOfConfigs()
|
||||
{
|
||||
// Arrange
|
||||
var configType = DisplayConfigEnums.ConfigTypes.ObservationCfg;
|
||||
var mockResult = new List<HistoricalConfigChanges>
|
||||
public async Task GetAll_ReturnsAllConfigChanges()
|
||||
{
|
||||
new(),
|
||||
new(),
|
||||
new()
|
||||
};
|
||||
_mockRepo.Setup(r => r.FindLastHistoricalConfigChangesByType(configType, 3)).ReturnsAsync(mockResult);
|
||||
|
||||
// Act
|
||||
var result = await _service.GetByType(configType, 3);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Has.Count.EqualTo(3));
|
||||
}
|
||||
// Arrange
|
||||
var mockResult = new List<HistoricalConfigChanges>
|
||||
{
|
||||
new(),
|
||||
new()
|
||||
};
|
||||
_mockRepo.Setup(r => r.FindAll()).ReturnsAsync(mockResult);
|
||||
|
||||
// Act
|
||||
var result = await _service.GetAll();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Has.Count.EqualTo(2));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the service's <c>GetByType</c> method returns the expected number of historical configuration changes for the specified configuration type.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetByUser_ReturnsCorrectConfigs()
|
||||
{
|
||||
// Arrange
|
||||
var user = "TestUser";
|
||||
var mockResult = new List<HistoricalConfigChanges>
|
||||
public async Task GetByType_ReturnsCorrectAmountOfConfigs()
|
||||
{
|
||||
new(),
|
||||
new()
|
||||
};
|
||||
_mockRepo.Setup(r => r.FindLastHistoricalConfigChangesByUser(user, null, 2)).ReturnsAsync(mockResult);
|
||||
|
||||
// Act
|
||||
var result = await _service.GetByUser(user, null, 2);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Has.Count.EqualTo(2));
|
||||
}
|
||||
// Arrange
|
||||
var configType = DisplayConfigEnums.ConfigTypes.ObservationCfg;
|
||||
var mockResult = new List<HistoricalConfigChanges>
|
||||
{
|
||||
new(),
|
||||
new(),
|
||||
new()
|
||||
};
|
||||
_mockRepo.Setup(r => r.FindLastHistoricalConfigChangesByType(configType, 3)).ReturnsAsync(mockResult);
|
||||
|
||||
// Act
|
||||
var result = await _service.GetByType(configType, 3);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Has.Count.EqualTo(3));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the service returns the expected number of historical configuration changes for a given user,
|
||||
/// confirming the repository result is correctly forwarded to the caller.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task UpdateHistoricalConfigChange_WhenExceptionOccurs_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
var mockChange = new HistoricalConfigChanges();
|
||||
_mockRepo.Setup(r => r.Update(mockChange)).Throws(new Exception());
|
||||
public async Task GetByUser_ReturnsCorrectConfigs()
|
||||
{
|
||||
// Arrange
|
||||
var user = "TestUser";
|
||||
var mockResult = new List<HistoricalConfigChanges>
|
||||
{
|
||||
new(),
|
||||
new()
|
||||
};
|
||||
_mockRepo.Setup(r => r.FindLastHistoricalConfigChangesByUser(user, null, 2)).ReturnsAsync(mockResult);
|
||||
|
||||
// Act
|
||||
var result = await _service.GetByUser(user, null, 2);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Has.Count.EqualTo(2));
|
||||
}
|
||||
|
||||
// Act
|
||||
var result = await _service.UpdateHistoricalConfigChange(mockChange);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
/// <summary>
|
||||
/// Verifies that the service returns null when an exception is thrown while updating a historical configuration change, ensuring graceful error handling.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task UpdateHistoricalConfigChange_WhenExceptionOccurs_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
var mockChange = new HistoricalConfigChanges();
|
||||
_mockRepo.Setup(r => r.Update(mockChange)).Throws(new Exception());
|
||||
|
||||
// Act
|
||||
var result = await _service.UpdateHistoricalConfigChange(mockChange);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
}
|
||||
@@ -9,113 +9,137 @@ public class InMemoryLockProviderTest
|
||||
{
|
||||
private InMemoryLockProvider _provider = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a fresh <see cref="InMemoryLockProvider"/> instance for the test fixture, ensuring each test starts with a clean, isolated provider state.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_provider = new InMemoryLockProvider();
|
||||
}
|
||||
public void SetUp()
|
||||
{
|
||||
_provider = new InMemoryLockProvider();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the private <c>_locks</c> dictionary from the associated <see cref="InMemoryLockProvider"/> instance using reflection, exposing the underlying locks for inspection or manipulation in tests.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="ConcurrentDictionary{TKey, TValue}"/> mapping lock keys to their <see cref="SemaphoreSlim"/> instances held by the provider.</returns>
|
||||
private ConcurrentDictionary<string, SemaphoreSlim> GetLocks()
|
||||
{
|
||||
var field = typeof(InMemoryLockProvider)
|
||||
.GetField("_locks", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
return (ConcurrentDictionary<string, SemaphoreSlim>)field!.GetValue(_provider)!;
|
||||
}
|
||||
{
|
||||
var field = typeof(InMemoryLockProvider)
|
||||
.GetField("_locks", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
return (ConcurrentDictionary<string, SemaphoreSlim>)field!.GetValue(_provider)!;
|
||||
}
|
||||
|
||||
#region TC-50
|
||||
/// <summary>
|
||||
/// Verifies that AcquireAsync returns <c>true</c> and creates a corresponding entry in the locks dictionary when called with a valid key and time span.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task AcquireAsync_ReturnsTrue_AndCreatesEntryInLocksDictionary()
|
||||
{
|
||||
var result = await _provider.AcquireAsync("key", TimeSpan.FromSeconds(1));
|
||||
|
||||
Assert.That(result, Is.True);
|
||||
|
||||
var locks = GetLocks();
|
||||
Assert.That(locks.ContainsKey("key"), Is.True);
|
||||
}
|
||||
public async Task AcquireAsync_ReturnsTrue_AndCreatesEntryInLocksDictionary()
|
||||
{
|
||||
var result = await _provider.AcquireAsync("key", TimeSpan.FromSeconds(1));
|
||||
|
||||
Assert.That(result, Is.True);
|
||||
|
||||
var locks = GetLocks();
|
||||
Assert.That(locks.ContainsKey("key"), Is.True);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TC-51
|
||||
/// <summary>
|
||||
/// Verifies that AcquireAsync returns false when the semaphore for the specified key is already occupied and the requested timeout expires before the lock can be acquired, and that the underlying semaphore is restored to a count of 1 after release.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task AcquireAsync_ReturnsFalse_WhenSemaphoreOccupiedAndTimeoutExpires()
|
||||
{
|
||||
await _provider.AcquireAsync("key", TimeSpan.FromSeconds(5));
|
||||
|
||||
var result = await _provider.AcquireAsync("key", TimeSpan.FromMilliseconds(100));
|
||||
|
||||
Assert.That(result, Is.False);
|
||||
|
||||
await _provider.ReleaseAsync("key");
|
||||
|
||||
var locks = GetLocks();
|
||||
Assert.That(locks["key"].CurrentCount, Is.EqualTo(1));
|
||||
}
|
||||
public async Task AcquireAsync_ReturnsFalse_WhenSemaphoreOccupiedAndTimeoutExpires()
|
||||
{
|
||||
await _provider.AcquireAsync("key", TimeSpan.FromSeconds(5));
|
||||
|
||||
var result = await _provider.AcquireAsync("key", TimeSpan.FromMilliseconds(100));
|
||||
|
||||
Assert.That(result, Is.False);
|
||||
|
||||
await _provider.ReleaseAsync("key");
|
||||
|
||||
var locks = GetLocks();
|
||||
Assert.That(locks["key"].CurrentCount, Is.EqualTo(1));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TC-52
|
||||
/// <summary>
|
||||
/// Verifies that calling <c>ReleaseAsync</c> on a semaphore provider restores availability,
|
||||
/// allowing a subsequent <c>AcquireAsync</c> for the same key to succeed and the semaphore's
|
||||
/// <c>CurrentCount</c> to transition back to its released value.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ReleaseAsync_MakesSemaphoreAvailableForNextAcquire()
|
||||
{
|
||||
await _provider.AcquireAsync("key", TimeSpan.FromSeconds(1));
|
||||
await _provider.ReleaseAsync("key");
|
||||
|
||||
var result = await _provider.AcquireAsync("key", TimeSpan.FromSeconds(1));
|
||||
|
||||
Assert.That(result, Is.True);
|
||||
|
||||
var locks = GetLocks();
|
||||
Assert.That(locks["key"].CurrentCount, Is.EqualTo(0));
|
||||
|
||||
await _provider.ReleaseAsync("key");
|
||||
|
||||
Assert.That(locks["key"].CurrentCount, Is.EqualTo(1));
|
||||
}
|
||||
public async Task ReleaseAsync_MakesSemaphoreAvailableForNextAcquire()
|
||||
{
|
||||
await _provider.AcquireAsync("key", TimeSpan.FromSeconds(1));
|
||||
await _provider.ReleaseAsync("key");
|
||||
|
||||
var result = await _provider.AcquireAsync("key", TimeSpan.FromSeconds(1));
|
||||
|
||||
Assert.That(result, Is.True);
|
||||
|
||||
var locks = GetLocks();
|
||||
Assert.That(locks["key"].CurrentCount, Is.EqualTo(0));
|
||||
|
||||
await _provider.ReleaseAsync("key");
|
||||
|
||||
Assert.That(locks["key"].CurrentCount, Is.EqualTo(1));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TC-53
|
||||
/// <summary>
|
||||
/// Verifies that <c>ReleaseAsync</c> does not throw when invoked without a prior <c>AcquireAsync</c> for the given key, and remains safe to call multiple times after a single successful acquire.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ReleaseAsync_DoesNotThrow_WhenCalledWithoutPriorAcquire()
|
||||
{
|
||||
await _provider.ReleaseAsync("nonexistent-key");
|
||||
|
||||
await _provider.AcquireAsync("key", TimeSpan.FromSeconds(1));
|
||||
await _provider.ReleaseAsync("key");
|
||||
await _provider.ReleaseAsync("key");
|
||||
}
|
||||
public async Task ReleaseAsync_DoesNotThrow_WhenCalledWithoutPriorAcquire()
|
||||
{
|
||||
await _provider.ReleaseAsync("nonexistent-key");
|
||||
|
||||
await _provider.AcquireAsync("key", TimeSpan.FromSeconds(1));
|
||||
await _provider.ReleaseAsync("key");
|
||||
await _provider.ReleaseAsync("key");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TC-54
|
||||
/// <summary>
|
||||
/// Verifies that <c>AcquireAsync</c> is thread-safe for a given key, ensuring that only one caller can hold the semaphore at a time even when multiple tasks compete concurrently for the same key, and that a single semaphore instance is created and reused per key.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task AcquireAsync_IsThreadSafe_OnlyOneHolderAtATime_SingleSemaphorePerKey()
|
||||
{
|
||||
const string key = "same-key";
|
||||
const int threadCount = 10;
|
||||
var acquiredCount = 0;
|
||||
var currentHolders = 0;
|
||||
|
||||
var tasks = Enumerable.Range(0, threadCount).Select(_ => Task.Run(async () =>
|
||||
public async Task AcquireAsync_IsThreadSafe_OnlyOneHolderAtATime_SingleSemaphorePerKey()
|
||||
{
|
||||
var acquired = await _provider.AcquireAsync(key, TimeSpan.FromSeconds(10));
|
||||
|
||||
Assert.That(acquired, Is.True);
|
||||
|
||||
var current = Interlocked.Increment(ref currentHolders);
|
||||
Assert.That(current, Is.EqualTo(1));
|
||||
|
||||
Interlocked.Increment(ref acquiredCount);
|
||||
await Task.Delay(5);
|
||||
|
||||
Interlocked.Decrement(ref currentHolders);
|
||||
await _provider.ReleaseAsync(key);
|
||||
})).ToArray();
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
|
||||
Assert.That(acquiredCount, Is.EqualTo(threadCount));
|
||||
|
||||
var locks = GetLocks();
|
||||
Assert.That(locks.ContainsKey(key), Is.True);
|
||||
Assert.That(locks.Keys.Count(k => k == key), Is.EqualTo(1));
|
||||
}
|
||||
const string key = "same-key";
|
||||
const int threadCount = 10;
|
||||
var acquiredCount = 0;
|
||||
var currentHolders = 0;
|
||||
|
||||
var tasks = Enumerable.Range(0, threadCount).Select(_ => Task.Run(async () =>
|
||||
{
|
||||
var acquired = await _provider.AcquireAsync(key, TimeSpan.FromSeconds(10));
|
||||
|
||||
Assert.That(acquired, Is.True);
|
||||
|
||||
var current = Interlocked.Increment(ref currentHolders);
|
||||
Assert.That(current, Is.EqualTo(1));
|
||||
|
||||
Interlocked.Increment(ref acquiredCount);
|
||||
await Task.Delay(5);
|
||||
|
||||
Interlocked.Decrement(ref currentHolders);
|
||||
await _provider.ReleaseAsync(key);
|
||||
})).ToArray();
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
|
||||
Assert.That(acquiredCount, Is.EqualTo(threadCount));
|
||||
|
||||
var locks = GetLocks();
|
||||
Assert.That(locks.ContainsKey(key), Is.True);
|
||||
Assert.That(locks.Keys.Count(k => k == key), Is.EqualTo(1));
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -15,25 +15,30 @@ namespace adas_core.Test.Services;
|
||||
[TestFixture]
|
||||
public class LightBeaconServiceTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the test fixture by creating mock instances of the service's dependencies
|
||||
/// and instantiating the <see cref="LightBeaconService"/> under test with those mocks.
|
||||
/// This setup runs before each test to ensure a clean, isolated test environment.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
_pocService = new Mock<IPointOfCareService>();
|
||||
_clientMessageService = new Mock<IClientMessageService>();
|
||||
_subscribersService = new Mock<ISubscribersService>();
|
||||
_logger = new Mock<ILogger<LightBeaconService>>();
|
||||
_lightBeaconRepository = new Mock<ILightBeaconRepository>();
|
||||
|
||||
_lightBeaconService = new LightBeaconService(
|
||||
_optionsApiSettings,
|
||||
_logger.Object,
|
||||
_clientMessageService.Object,
|
||||
_subscribersService.Object,
|
||||
_pocService.Object,
|
||||
_lightBeaconRepository.Object
|
||||
);
|
||||
}
|
||||
public void Setup()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
_pocService = new Mock<IPointOfCareService>();
|
||||
_clientMessageService = new Mock<IClientMessageService>();
|
||||
_subscribersService = new Mock<ISubscribersService>();
|
||||
_logger = new Mock<ILogger<LightBeaconService>>();
|
||||
_lightBeaconRepository = new Mock<ILightBeaconRepository>();
|
||||
|
||||
_lightBeaconService = new LightBeaconService(
|
||||
_optionsApiSettings,
|
||||
_logger.Object,
|
||||
_clientMessageService.Object,
|
||||
_subscribersService.Object,
|
||||
_pocService.Object,
|
||||
_lightBeaconRepository.Object
|
||||
);
|
||||
}
|
||||
|
||||
private LightBeaconService _lightBeaconService = null!;
|
||||
|
||||
@@ -51,20 +56,23 @@ public class LightBeaconServiceTest
|
||||
private Mock<ISubscribersService> _subscribersService = null!;
|
||||
private Mock<ILightBeaconRepository> _lightBeaconRepository = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Integration test that verifies the light beacon service returns <see cref="LightBeaconColor.Off"/> for a given point of care when the patient has no associated beacon color.
|
||||
/// </summary>
|
||||
[Ignore("Integration test")]
|
||||
[Test]
|
||||
public async Task GetBeaconColor()
|
||||
{
|
||||
var patient = new Patient
|
||||
[Test]
|
||||
public async Task GetBeaconColor()
|
||||
{
|
||||
UnitId = ObjectId.GenerateNewId(),
|
||||
PointOfCareId = ObjectId.GenerateNewId()
|
||||
};
|
||||
|
||||
|
||||
var color = await _lightBeaconService.GetColor(patient.PointOfCareId.Value);
|
||||
|
||||
Assert.That(color, Is.EqualTo(
|
||||
LightBeaconColor.Off));
|
||||
}
|
||||
var patient = new Patient
|
||||
{
|
||||
UnitId = ObjectId.GenerateNewId(),
|
||||
PointOfCareId = ObjectId.GenerateNewId()
|
||||
};
|
||||
|
||||
|
||||
var color = await _lightBeaconService.GetColor(patient.PointOfCareId.Value);
|
||||
|
||||
Assert.That(color, Is.EqualTo(
|
||||
LightBeaconColor.Off));
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,11 @@ namespace adas_core.Test.Services;
|
||||
[TestFixture]
|
||||
public class MasterListServiceTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes all required mock dependencies and constructs a <see cref="MasterListService{MasterList}"/> instance
|
||||
/// for use in unit tests. Configures the HTTP context with a test user principal, registers the master list repository
|
||||
/// in the service provider, and supplies default API settings.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
@@ -83,6 +88,9 @@ public class MasterListServiceTest
|
||||
private MasterListService<MasterList> _service = null!;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>DeleteMasterListById</c> invokes the repository's <c>Delete</c> method once with the provided identifier when the master list is found.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task DeleteMasterListById_ShouldCallRepositoryDelete_WhenMasterListFound()
|
||||
{
|
||||
@@ -117,6 +125,9 @@ public class MasterListServiceTest
|
||||
// Assert.That(masterLists, Is.EqualTo(result));
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the service returns the master list when it is found by the specified id.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetMasterListById_ShouldReturnMasterList_WhenFound()
|
||||
{
|
||||
@@ -133,6 +144,9 @@ public class MasterListServiceTest
|
||||
Assert.That(masterList, Is.EqualTo(result));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>GetMasterListByName</c> returns the matching <see cref="MasterList"/> when a master list with the specified name is found in the repository.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetMasterListByName_ShouldReturnMasterList_WhenFound()
|
||||
{
|
||||
@@ -149,6 +163,9 @@ public class MasterListServiceTest
|
||||
Assert.That(masterList, Is.EqualTo(result));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the InsertMasterList service method returns the same <see cref="MasterList"/> instance that was inserted, ensuring the service correctly retrieves the inserted entity by its identifier after persistence.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task InsertMasterList_ShouldReturnInsertedMasterList()
|
||||
{
|
||||
@@ -166,6 +183,10 @@ public class MasterListServiceTest
|
||||
Assert.That(masterList, Is.EqualTo(result));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that UpdateMasterList returns the updated master list when the repository successfully completes the update and finds the entity by id.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous test execution.</returns>
|
||||
[Test]
|
||||
public async Task UpdateMasterList_ShouldReturnUpdatedMasterList()
|
||||
{
|
||||
|
||||
@@ -7,11 +7,15 @@ public class NoCacheServiceTest
|
||||
{
|
||||
private NoCacheService _noCacheService = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a fresh <see cref="NoCacheService"/> instance and assigns it to <c>_noCacheService</c>
|
||||
/// to provide a clean, dependency-free test fixture prior to executing each test.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_noCacheService = new NoCacheService();
|
||||
}
|
||||
public void SetUp()
|
||||
{
|
||||
_noCacheService = new NoCacheService();
|
||||
}
|
||||
|
||||
#region TC-27
|
||||
|
||||
@@ -67,75 +71,92 @@ public class NoCacheServiceTest
|
||||
|
||||
#region TC-28
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the no-cache service implementation never persists data to any backend when <c>GetOrSetObjectAsync</c> is invoked, and confirms that a subsequent <c>DeleteObjectAsync</c> on the same key does not throw.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetOrSetObjectAsync_DoesNotStoreData_InAnyBackend()
|
||||
{
|
||||
var key = "patients:abc123";
|
||||
var expectedResult = new { Name = "TestPatient" };
|
||||
|
||||
Func<Task<object>> factory = () => Task.FromResult<object>(expectedResult);
|
||||
|
||||
await _noCacheService.GetOrSetObjectAsync(key, factory);
|
||||
|
||||
var retrieved = await _noCacheService.GetObjectAsync<object>(key);
|
||||
Assert.That(retrieved, Is.Null);
|
||||
|
||||
|
||||
Func<Task> act = async () => await _noCacheService.DeleteObjectAsync(key);
|
||||
Assert.That(act, Throws.Nothing);
|
||||
|
||||
}
|
||||
public async Task GetOrSetObjectAsync_DoesNotStoreData_InAnyBackend()
|
||||
{
|
||||
var key = "patients:abc123";
|
||||
var expectedResult = new { Name = "TestPatient" };
|
||||
|
||||
Func<Task<object>> factory = () => Task.FromResult<object>(expectedResult);
|
||||
|
||||
await _noCacheService.GetOrSetObjectAsync(key, factory);
|
||||
|
||||
var retrieved = await _noCacheService.GetObjectAsync<object>(key);
|
||||
Assert.That(retrieved, Is.Null);
|
||||
|
||||
|
||||
Func<Task> act = async () => await _noCacheService.DeleteObjectAsync(key);
|
||||
Assert.That(act, Throws.Nothing);
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region TC-29
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the no-cache service's <c>DeleteByPatternAsync</c> returns 0 and does not throw when invoked with arbitrary patterns, confirming the no-op delete behavior for any key pattern.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task DeleteByPatternAsync_ReturnsZero_DoesNotThrow()
|
||||
{
|
||||
// Act
|
||||
var result = await _noCacheService.DeleteByPatternAsync("patients:*");
|
||||
var result2 = await _noCacheService.DeleteByPatternAsync("any:pattern:*");
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(0));
|
||||
Assert.That(result2, Is.EqualTo(0));
|
||||
}
|
||||
public async Task DeleteByPatternAsync_ReturnsZero_DoesNotThrow()
|
||||
{
|
||||
// Act
|
||||
var result = await _noCacheService.DeleteByPatternAsync("patients:*");
|
||||
var result2 = await _noCacheService.DeleteByPatternAsync("any:pattern:*");
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(0));
|
||||
Assert.That(result2, Is.EqualTo(0));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region TC-30
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that calling CleanCache on the no-cache service is a safe no-op that does not throw,
|
||||
/// and that subsequent calls to GetValue consistently return <c>null</c> for any key.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CleanCache_IsNoOp_DoesNotThrow()
|
||||
{
|
||||
|
||||
Action act = () => _noCacheService.CleanCache();
|
||||
Assert.That(act, Throws.Nothing);
|
||||
|
||||
var result = _noCacheService.GetValue("any-key");
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
public void CleanCache_IsNoOp_DoesNotThrow()
|
||||
{
|
||||
|
||||
Action act = () => _noCacheService.CleanCache();
|
||||
Assert.That(act, Throws.Nothing);
|
||||
|
||||
var result = _noCacheService.GetValue("any-key");
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that calling <c>SetValue</c> on the no-cache service is a no-op and does not throw any exception.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void SetValue_IsNoOp_DoesNotThrow()
|
||||
{
|
||||
|
||||
Action act = () => _noCacheService.SetValue("key", "value");
|
||||
Assert.That(act, Throws.Nothing);
|
||||
|
||||
}
|
||||
public void SetValue_IsNoOp_DoesNotThrow()
|
||||
{
|
||||
|
||||
Action act = () => _noCacheService.SetValue("key", "value");
|
||||
Assert.That(act, Throws.Nothing);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the no-cache service's GetValue method returns null for any key,
|
||||
/// confirming that the no-op implementation does not return or simulate cached values.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void GetValue_IsNoOp_ReturnsNull()
|
||||
{
|
||||
var result = _noCacheService.GetValue("any-key");
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
public void GetValue_IsNoOp_ReturnsNull()
|
||||
{
|
||||
var result = _noCacheService.GetValue("any-key");
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -21,98 +21,104 @@ namespace adas_core.Test.Services;
|
||||
[TestFixture]
|
||||
public class ObservationServiceTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the test fixture for the <see cref="ObservationService"/> by creating and configuring
|
||||
/// all required dependency mocks, instantiating the service under test with the mocked collaborators,
|
||||
/// and pre-configuring common lookup behavior for the default "UCI5C" unit (including <c>FindByName</c>
|
||||
/// and <c>FindById</c>) along with the <c>ICalculatedObservationsService.Map</c> passthrough.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
//_observationServiceMock = new Mock<IObservationService>();
|
||||
|
||||
//var medicineServiceMock = new Mock<IMedicineService>();1
|
||||
var groupedObservationServiceMock = new Mock<IGroupedObservationService>();
|
||||
var alarmServiceMock = new Mock<IAlarmService>();
|
||||
|
||||
var clientMessageServiceMock = new Mock<IClientMessageService>();
|
||||
|
||||
var subscribersServiceMock = new Mock<ISubscribersService>();
|
||||
|
||||
var subscriberGroupedServiceMock = new Mock<ISubscriberGroupedService>();
|
||||
|
||||
_patientServiceMock = new Mock<IPatientService>();
|
||||
|
||||
_configObservationService = new Mock<IConfigObservationService>();
|
||||
|
||||
_observationRepository = new Mock<IObservationRepository>();
|
||||
|
||||
var observationArchiveRepository = new Mock<IObservationArchiveRepository>();
|
||||
|
||||
var calculatedObservationsServiceMock = new Mock<ICalculatedObservationsService>();
|
||||
var calculatedObservationsServiceLazy =
|
||||
new Lazy<ICalculatedObservationsService>(() => calculatedObservationsServiceMock.Object);
|
||||
calculatedObservationsServiceMock.Setup(o => o.Map(It.IsAny<PatientObservation>(), It.IsAny<bool>()))
|
||||
.ReturnsAsync((PatientObservation obs, bool _) => obs);
|
||||
|
||||
_configUnitsService = new Mock<IConfigUnitsService>();
|
||||
_unitServiceMock = new Mock<IUnitService>();
|
||||
|
||||
var diagnosisServiceMock = new Mock<IDiagnosisService>();
|
||||
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
Options.Create(_recordingSettings);
|
||||
_optionsCacheSettings = Options.Create(_cacheSettings);
|
||||
|
||||
var balizaService = new Mock<ILightBeaconService>();
|
||||
var pocService = new Mock<IPointOfCareService>();
|
||||
var relayService = new Mock<IRelayService>();
|
||||
var recordingService = new Mock<IRecordingService>();
|
||||
|
||||
_logger = new Mock<ILogger<ObservationService>>();
|
||||
|
||||
_observationService = new ObservationService(
|
||||
_patientServiceMock.Object,
|
||||
//Ipoc.Object,
|
||||
_configObservationService.Object,
|
||||
_observationRepository.Object,
|
||||
observationArchiveRepository.Object,
|
||||
_configUnitsService.Object,
|
||||
diagnosisServiceMock.Object,
|
||||
_optionsApiSettings,
|
||||
_optionsCacheSettings,
|
||||
balizaService.Object,
|
||||
relayService.Object,
|
||||
recordingService.Object,
|
||||
_logger.Object,
|
||||
groupedObservationServiceMock.Object,
|
||||
alarmServiceMock.Object,
|
||||
clientMessageServiceMock.Object,
|
||||
subscribersServiceMock.Object,
|
||||
subscriberGroupedServiceMock.Object,
|
||||
calculatedObservationsServiceLazy,
|
||||
_httpContextAccessor.Object,
|
||||
_auditService.Object,
|
||||
pocService.Object,
|
||||
Mock.Of<ICacheService>()
|
||||
);
|
||||
|
||||
// Create a mock of the singleton class subscribers
|
||||
var mockSingleton = new Mock<ICalculatedObservationsService>();
|
||||
|
||||
// Set up the mock object to return a specific value when a method is called
|
||||
mockSingleton.Setup(x => x.Map(It.IsAny<PatientObservation>(), It.IsAny<bool>()))
|
||||
.ReturnsAsync((PatientObservation? value, bool _) => value);
|
||||
var unitId = ObjectId.GenerateNewId();
|
||||
var unit = new Unit
|
||||
public void Setup()
|
||||
{
|
||||
Id = unitId,
|
||||
Name = "UCI5C",
|
||||
Title = "CONTROLC",
|
||||
Configuration = new UnitConfiguration
|
||||
//_observationServiceMock = new Mock<IObservationService>();
|
||||
|
||||
//var medicineServiceMock = new Mock<IMedicineService>();1
|
||||
var groupedObservationServiceMock = new Mock<IGroupedObservationService>();
|
||||
var alarmServiceMock = new Mock<IAlarmService>();
|
||||
|
||||
var clientMessageServiceMock = new Mock<IClientMessageService>();
|
||||
|
||||
var subscribersServiceMock = new Mock<ISubscribersService>();
|
||||
|
||||
var subscriberGroupedServiceMock = new Mock<ISubscriberGroupedService>();
|
||||
|
||||
_patientServiceMock = new Mock<IPatientService>();
|
||||
|
||||
_configObservationService = new Mock<IConfigObservationService>();
|
||||
|
||||
_observationRepository = new Mock<IObservationRepository>();
|
||||
|
||||
var observationArchiveRepository = new Mock<IObservationArchiveRepository>();
|
||||
|
||||
var calculatedObservationsServiceMock = new Mock<ICalculatedObservationsService>();
|
||||
var calculatedObservationsServiceLazy =
|
||||
new Lazy<ICalculatedObservationsService>(() => calculatedObservationsServiceMock.Object);
|
||||
calculatedObservationsServiceMock.Setup(o => o.Map(It.IsAny<PatientObservation>(), It.IsAny<bool>()))
|
||||
.ReturnsAsync((PatientObservation obs, bool _) => obs);
|
||||
|
||||
_configUnitsService = new Mock<IConfigUnitsService>();
|
||||
_unitServiceMock = new Mock<IUnitService>();
|
||||
|
||||
var diagnosisServiceMock = new Mock<IDiagnosisService>();
|
||||
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
Options.Create(_recordingSettings);
|
||||
_optionsCacheSettings = Options.Create(_cacheSettings);
|
||||
|
||||
var balizaService = new Mock<ILightBeaconService>();
|
||||
var pocService = new Mock<IPointOfCareService>();
|
||||
var relayService = new Mock<IRelayService>();
|
||||
var recordingService = new Mock<IRecordingService>();
|
||||
|
||||
_logger = new Mock<ILogger<ObservationService>>();
|
||||
|
||||
_observationService = new ObservationService(
|
||||
_patientServiceMock.Object,
|
||||
//Ipoc.Object,
|
||||
_configObservationService.Object,
|
||||
_observationRepository.Object,
|
||||
observationArchiveRepository.Object,
|
||||
_configUnitsService.Object,
|
||||
diagnosisServiceMock.Object,
|
||||
_optionsApiSettings,
|
||||
_optionsCacheSettings,
|
||||
balizaService.Object,
|
||||
relayService.Object,
|
||||
recordingService.Object,
|
||||
_logger.Object,
|
||||
groupedObservationServiceMock.Object,
|
||||
alarmServiceMock.Object,
|
||||
clientMessageServiceMock.Object,
|
||||
subscribersServiceMock.Object,
|
||||
subscriberGroupedServiceMock.Object,
|
||||
calculatedObservationsServiceLazy,
|
||||
_httpContextAccessor.Object,
|
||||
_auditService.Object,
|
||||
pocService.Object,
|
||||
Mock.Of<ICacheService>()
|
||||
);
|
||||
|
||||
// Create a mock of the singleton class subscribers
|
||||
var mockSingleton = new Mock<ICalculatedObservationsService>();
|
||||
|
||||
// Set up the mock object to return a specific value when a method is called
|
||||
mockSingleton.Setup(x => x.Map(It.IsAny<PatientObservation>(), It.IsAny<bool>()))
|
||||
.ReturnsAsync((PatientObservation? value, bool _) => value);
|
||||
var unitId = ObjectId.GenerateNewId();
|
||||
var unit = new Unit
|
||||
{
|
||||
AutoAdt = true
|
||||
}
|
||||
};
|
||||
|
||||
_unitServiceMock.Setup(u => u.FindByName(unit.Name)).ReturnsAsync(unit);
|
||||
_unitServiceMock.Setup(u => u.FindById(unit.Id)).ReturnsAsync(unit);
|
||||
}
|
||||
Id = unitId,
|
||||
Name = "UCI5C",
|
||||
Title = "CONTROLC",
|
||||
Configuration = new UnitConfiguration
|
||||
{
|
||||
AutoAdt = true
|
||||
}
|
||||
};
|
||||
|
||||
_unitServiceMock.Setup(u => u.FindByName(unit.Name)).ReturnsAsync(unit);
|
||||
_unitServiceMock.Setup(u => u.FindById(unit.Id)).ReturnsAsync(unit);
|
||||
}
|
||||
|
||||
private ObservationService _observationService;
|
||||
|
||||
@@ -637,172 +643,178 @@ public class ObservationServiceTest
|
||||
)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that when an isolation observation is processed through SaveRequest, the configuration observation and units mapping services are invoked, and the resulting mapped observation is inserted into the observation repository with the expected value, patient identifier, name, time, message time, and coding system.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ProcessIsolationObservation_Return_IsolationObs()
|
||||
{
|
||||
var patientObs = new Person
|
||||
public async Task ProcessIsolationObservation_Return_IsolationObs()
|
||||
{
|
||||
FirstName = "Miguel",
|
||||
LastName = "Villanueva",
|
||||
Ids = new Dictionary<string, string> { { "MR", "437537" } }
|
||||
};
|
||||
|
||||
var patient = new Patient
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
UnitId = ObjectId.GenerateNewId(),
|
||||
UnitString = "UCI5C",
|
||||
Bed = "Box4",
|
||||
PatientNumber = "437537",
|
||||
Person = patientObs
|
||||
};
|
||||
|
||||
var apiRequest = new ApiRequest
|
||||
{
|
||||
Location = new PatientLocation("UCI5C", "Box4"),
|
||||
ObservationData = new ObservationData
|
||||
var patientObs = new Person
|
||||
{
|
||||
Code = "302147001",
|
||||
CodingSystem = "SNM",
|
||||
Value = "Aire; Contacto; Preventivo",
|
||||
Text = "Aislamiento",
|
||||
Time = Now
|
||||
},
|
||||
Observations =
|
||||
[
|
||||
new PatientObservation
|
||||
FirstName = "Miguel",
|
||||
LastName = "Villanueva",
|
||||
Ids = new Dictionary<string, string> { { "MR", "437537" } }
|
||||
};
|
||||
|
||||
var patient = new Patient
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
UnitId = ObjectId.GenerateNewId(),
|
||||
UnitString = "UCI5C",
|
||||
Bed = "Box4",
|
||||
PatientNumber = "437537",
|
||||
Person = patientObs
|
||||
};
|
||||
|
||||
var apiRequest = new ApiRequest
|
||||
{
|
||||
Location = new PatientLocation("UCI5C", "Box4"),
|
||||
ObservationData = new ObservationData
|
||||
{
|
||||
Code = "code",
|
||||
Code = "302147001",
|
||||
CodingSystem = "SNM",
|
||||
Name = "name",
|
||||
Status = StatusEnum.Type.Ok,
|
||||
Time = Now,
|
||||
Value = "value"
|
||||
}
|
||||
],
|
||||
Patient = patientObs,
|
||||
PatientNumber = "437537",
|
||||
Type = "ORU_R01",
|
||||
PatientId = PatientId.ToString(),
|
||||
MessageTime = Now
|
||||
};
|
||||
|
||||
var newObs = new PatientObservation
|
||||
{
|
||||
Value = "Aire, Contacto, Preventivo",
|
||||
Name = "Isolation",
|
||||
CodingSystem = "ADAS",
|
||||
PatientId = patient.Id,
|
||||
MessageTime = Now,
|
||||
Time = Now
|
||||
};
|
||||
|
||||
_patientServiceMock.Setup(cm => cm.FindPatientByApiRequest(apiRequest)).ReturnsAsync(patient);
|
||||
_configObservationService
|
||||
.Setup(o => o.Map(It.Is<PatientObservation>(arg => arg.PatientId == patient.Id), false))
|
||||
.ReturnsAsync(newObs);
|
||||
_configUnitsService.Setup(o => o.Map(It.Is<PatientObservation>(arg => arg.PatientId == patient.Id)))
|
||||
.ReturnsAsync(newObs);
|
||||
_configObservationService.Setup(o => o.RetentionActions(It.IsAny<PatientObservation>()))
|
||||
.ReturnsAsync(new ObservatitonRetentionResult());
|
||||
_unitServiceMock.Setup(o => o.FindById(It.IsAny<ObjectId>())).ReturnsAsync(new Unit
|
||||
{ Configuration = new UnitConfiguration { AutoAdt = true } });
|
||||
await _observationService.SaveRequest(apiRequest);
|
||||
|
||||
|
||||
_observationRepository.Verify(o => o.InsertOneAsync(It.Is<PatientObservation>(arg =>
|
||||
arg.Value == newObs.Value &&
|
||||
arg.PatientId == newObs.PatientId &&
|
||||
arg.Name == newObs.Name &&
|
||||
arg.Time == newObs.Time &&
|
||||
arg.MessageTime == newObs.MessageTime &&
|
||||
arg.CodingSystem == newObs.CodingSystem
|
||||
)));
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public async Task ProcessPositionObservation_Return_PositionObs()
|
||||
{
|
||||
var patientObs = new Person
|
||||
{
|
||||
FirstName = "Miguel",
|
||||
LastName = "Villanueva",
|
||||
Ids = new Dictionary<string, string> { { "MR", "437537" } }
|
||||
};
|
||||
|
||||
var patient = new Patient
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
UnitId = ObjectId.GenerateNewId(),
|
||||
UnitString = "UCI5C",
|
||||
Bed = "Box4",
|
||||
PatientNumber = "437537",
|
||||
Person = patientObs
|
||||
};
|
||||
|
||||
var apiRequest = new ApiRequest
|
||||
{
|
||||
Location = new PatientLocation("UCI5C", "Box4"),
|
||||
ObservationData = new ObservationData
|
||||
Value = "Aire; Contacto; Preventivo",
|
||||
Text = "Aislamiento",
|
||||
Time = Now
|
||||
},
|
||||
Observations =
|
||||
[
|
||||
new PatientObservation
|
||||
{
|
||||
Code = "code",
|
||||
CodingSystem = "SNM",
|
||||
Name = "name",
|
||||
Status = StatusEnum.Type.Ok,
|
||||
Time = Now,
|
||||
Value = "value"
|
||||
}
|
||||
],
|
||||
Patient = patientObs,
|
||||
PatientNumber = "437537",
|
||||
Type = "ORU_R01",
|
||||
PatientId = PatientId.ToString(),
|
||||
MessageTime = Now
|
||||
};
|
||||
|
||||
var newObs = new PatientObservation
|
||||
{
|
||||
Value = "Aire, Contacto, Preventivo",
|
||||
Name = "Isolation",
|
||||
CodingSystem = "ADAS",
|
||||
PatientId = patient.Id,
|
||||
MessageTime = Now,
|
||||
Time = Now
|
||||
};
|
||||
|
||||
_patientServiceMock.Setup(cm => cm.FindPatientByApiRequest(apiRequest)).ReturnsAsync(patient);
|
||||
_configObservationService
|
||||
.Setup(o => o.Map(It.Is<PatientObservation>(arg => arg.PatientId == patient.Id), false))
|
||||
.ReturnsAsync(newObs);
|
||||
_configUnitsService.Setup(o => o.Map(It.Is<PatientObservation>(arg => arg.PatientId == patient.Id)))
|
||||
.ReturnsAsync(newObs);
|
||||
_configObservationService.Setup(o => o.RetentionActions(It.IsAny<PatientObservation>()))
|
||||
.ReturnsAsync(new ObservatitonRetentionResult());
|
||||
_unitServiceMock.Setup(o => o.FindById(It.IsAny<ObjectId>())).ReturnsAsync(new Unit
|
||||
{ Configuration = new UnitConfiguration { AutoAdt = true } });
|
||||
await _observationService.SaveRequest(apiRequest);
|
||||
|
||||
|
||||
_observationRepository.Verify(o => o.InsertOneAsync(It.Is<PatientObservation>(arg =>
|
||||
arg.Value == newObs.Value &&
|
||||
arg.PatientId == newObs.PatientId &&
|
||||
arg.Name == newObs.Name &&
|
||||
arg.Time == newObs.Time &&
|
||||
arg.MessageTime == newObs.MessageTime &&
|
||||
arg.CodingSystem == newObs.CodingSystem
|
||||
)));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that processing a position observation through the observation service persists a new <see cref="PatientObservation"/> with the expected values (Value, PatientId, Name, Time, MessageTime, and CodingSystem) when a valid API request is provided.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ProcessPositionObservation_Return_PositionObs()
|
||||
{
|
||||
var patientObs = new Person
|
||||
{
|
||||
FirstName = "Miguel",
|
||||
LastName = "Villanueva",
|
||||
Ids = new Dictionary<string, string> { { "MR", "437537" } }
|
||||
};
|
||||
|
||||
var patient = new Patient
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
UnitId = ObjectId.GenerateNewId(),
|
||||
UnitString = "UCI5C",
|
||||
Bed = "Box4",
|
||||
PatientNumber = "437537",
|
||||
Person = patientObs
|
||||
};
|
||||
|
||||
var apiRequest = new ApiRequest
|
||||
{
|
||||
Location = new PatientLocation("UCI5C", "Box4"),
|
||||
ObservationData = new ObservationData
|
||||
{
|
||||
Code = "386053000",
|
||||
CodingSystem = "SNM",
|
||||
Text = "CAMBIOS POSTURALES",
|
||||
Value = "Cama Hill-rom",
|
||||
Time = Now
|
||||
},
|
||||
Observations =
|
||||
[
|
||||
new PatientObservation
|
||||
{
|
||||
Code = "code",
|
||||
CodingSystem = "SNM",
|
||||
Name = "name",
|
||||
Status = StatusEnum.Type.Ok,
|
||||
Time = Now,
|
||||
Value = "Cama Hill-rom"
|
||||
}
|
||||
],
|
||||
Patient = patientObs,
|
||||
PatientNumber = "437537",
|
||||
Type = "ORU_R01",
|
||||
PatientId = PatientId.ToString(),
|
||||
MessageTime = Now
|
||||
};
|
||||
|
||||
var newObs = new PatientObservation
|
||||
{
|
||||
Code = "386053000",
|
||||
CodingSystem = "SNM",
|
||||
Text = "CAMBIOS POSTURALES",
|
||||
Value = "Cama Hill-rom",
|
||||
Name = "Patient_Position",
|
||||
CodingSystem = "ADAS",
|
||||
PatientId = patient.Id,
|
||||
MessageTime = Now,
|
||||
Time = Now
|
||||
},
|
||||
Observations =
|
||||
[
|
||||
new PatientObservation
|
||||
{
|
||||
Code = "code",
|
||||
CodingSystem = "SNM",
|
||||
Name = "name",
|
||||
Status = StatusEnum.Type.Ok,
|
||||
Time = Now,
|
||||
Value = "Cama Hill-rom"
|
||||
}
|
||||
],
|
||||
Patient = patientObs,
|
||||
PatientNumber = "437537",
|
||||
Type = "ORU_R01",
|
||||
PatientId = PatientId.ToString(),
|
||||
MessageTime = Now
|
||||
};
|
||||
|
||||
var newObs = new PatientObservation
|
||||
{
|
||||
Value = "Cama Hill-rom",
|
||||
Name = "Patient_Position",
|
||||
CodingSystem = "ADAS",
|
||||
PatientId = patient.Id,
|
||||
MessageTime = Now,
|
||||
Time = Now
|
||||
};
|
||||
|
||||
_patientServiceMock.Setup(cm => cm.FindPatientByApiRequest(apiRequest)).ReturnsAsync(patient);
|
||||
_configObservationService
|
||||
.Setup(o => o.Map(It.Is<PatientObservation>(arg => arg.PatientId == patient.Id), false))
|
||||
.ReturnsAsync(newObs);
|
||||
_configUnitsService.Setup(o => o.Map(It.Is<PatientObservation>(arg => arg.PatientId == patient.Id)))
|
||||
.ReturnsAsync(newObs);
|
||||
_configObservationService.Setup(o => o.RetentionActions(It.IsAny<PatientObservation>()))
|
||||
.ReturnsAsync(new ObservatitonRetentionResult());
|
||||
_unitServiceMock.Setup(o => o.FindById(It.IsAny<ObjectId>())).ReturnsAsync(new Unit
|
||||
{ Configuration = new UnitConfiguration { AutoAdt = true } });
|
||||
await _observationService.SaveRequest(apiRequest);
|
||||
|
||||
|
||||
_observationRepository.Verify(o => o.InsertOneAsync(It.Is<PatientObservation>(arg =>
|
||||
arg.Value == newObs.Value &&
|
||||
arg.PatientId == newObs.PatientId &&
|
||||
arg.Name == newObs.Name &&
|
||||
arg.Time == newObs.Time &&
|
||||
arg.MessageTime == newObs.MessageTime &&
|
||||
arg.CodingSystem == newObs.CodingSystem
|
||||
)));
|
||||
}
|
||||
};
|
||||
|
||||
_patientServiceMock.Setup(cm => cm.FindPatientByApiRequest(apiRequest)).ReturnsAsync(patient);
|
||||
_configObservationService
|
||||
.Setup(o => o.Map(It.Is<PatientObservation>(arg => arg.PatientId == patient.Id), false))
|
||||
.ReturnsAsync(newObs);
|
||||
_configUnitsService.Setup(o => o.Map(It.Is<PatientObservation>(arg => arg.PatientId == patient.Id)))
|
||||
.ReturnsAsync(newObs);
|
||||
_configObservationService.Setup(o => o.RetentionActions(It.IsAny<PatientObservation>()))
|
||||
.ReturnsAsync(new ObservatitonRetentionResult());
|
||||
_unitServiceMock.Setup(o => o.FindById(It.IsAny<ObjectId>())).ReturnsAsync(new Unit
|
||||
{ Configuration = new UnitConfiguration { AutoAdt = true } });
|
||||
await _observationService.SaveRequest(apiRequest);
|
||||
|
||||
|
||||
_observationRepository.Verify(o => o.InsertOneAsync(It.Is<PatientObservation>(arg =>
|
||||
arg.Value == newObs.Value &&
|
||||
arg.PatientId == newObs.PatientId &&
|
||||
arg.Name == newObs.Name &&
|
||||
arg.Time == newObs.Time &&
|
||||
arg.MessageTime == newObs.MessageTime &&
|
||||
arg.CodingSystem == newObs.CodingSystem
|
||||
)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ProcessIntravenousLinesObservation_Return_PositionObs()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,47 +17,52 @@ namespace adas_core.Test.Services;
|
||||
[TestFixture]
|
||||
public class PointOfCareServiceTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the mock dependencies and test environment required for unit testing the <see cref="PointOfCareService"/>.
|
||||
/// Configures repository, service, cache, admission, unit, and HTTP context mocks, including a simulated authenticated user
|
||||
/// and cache behavior that invokes the supplied factory directly to return the produced <see cref="PointOfCare"/> instance.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_pointOfCareRepositoryMock = new Mock<IPointOfCareRepository>();
|
||||
_unitServiceMock = new Mock<IUnitService>();
|
||||
_admissionServiceMock = new Mock<IAdmissionService>();
|
||||
_cacheServiceMock = new Mock<ICacheService>();
|
||||
_cacheServiceMock
|
||||
.Setup(c => c.GetOrSetObjectAsync(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<Func<Task<PointOfCare?>>>(),
|
||||
It.IsAny<TimeSpan?>(),
|
||||
It.IsAny<CancellationToken>()))
|
||||
.Returns((string _, Func<Task<PointOfCare?>> factory, TimeSpan? _, CancellationToken _) => factory());
|
||||
|
||||
var loggerMock = new Mock<ILogger<PointOfCareService>>();
|
||||
var userClaims = new ClaimsPrincipal(new ClaimsIdentity([
|
||||
new Claim(ClaimTypes.Name, "TestUser")
|
||||
], "mock"));
|
||||
|
||||
var httpContextMock = new DefaultHttpContext
|
||||
public void SetUp()
|
||||
{
|
||||
User = userClaims
|
||||
};
|
||||
|
||||
_httpContextAccessorMock.Setup(accessor => accessor.HttpContext)
|
||||
.Returns(httpContextMock);
|
||||
_pointOfCareService = new PointOfCareService(
|
||||
loggerMock.Object,
|
||||
_pointOfCareRepositoryMock.Object,
|
||||
new Lazy<IPatientService>(Mock.Of<IPatientService>),
|
||||
new Lazy<IUnitService>(() => _unitServiceMock.Object),
|
||||
Mock.Of<ISubscribersService>(),
|
||||
Mock.Of<Lazy<IClientMessageService>>(),
|
||||
new Lazy<IAdmissionService>(() => _admissionServiceMock.Object),
|
||||
_httpContextAccessorMock.Object,
|
||||
_auditServiceMock.Object,
|
||||
_cacheServiceMock.Object,
|
||||
Options.Create(new CacheSettings())
|
||||
);
|
||||
}
|
||||
_pointOfCareRepositoryMock = new Mock<IPointOfCareRepository>();
|
||||
_unitServiceMock = new Mock<IUnitService>();
|
||||
_admissionServiceMock = new Mock<IAdmissionService>();
|
||||
_cacheServiceMock = new Mock<ICacheService>();
|
||||
_cacheServiceMock
|
||||
.Setup(c => c.GetOrSetObjectAsync(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<Func<Task<PointOfCare?>>>(),
|
||||
It.IsAny<TimeSpan?>(),
|
||||
It.IsAny<CancellationToken>()))
|
||||
.Returns((string _, Func<Task<PointOfCare?>> factory, TimeSpan? _, CancellationToken _) => factory());
|
||||
|
||||
var loggerMock = new Mock<ILogger<PointOfCareService>>();
|
||||
var userClaims = new ClaimsPrincipal(new ClaimsIdentity([
|
||||
new Claim(ClaimTypes.Name, "TestUser")
|
||||
], "mock"));
|
||||
|
||||
var httpContextMock = new DefaultHttpContext
|
||||
{
|
||||
User = userClaims
|
||||
};
|
||||
|
||||
_httpContextAccessorMock.Setup(accessor => accessor.HttpContext)
|
||||
.Returns(httpContextMock);
|
||||
_pointOfCareService = new PointOfCareService(
|
||||
loggerMock.Object,
|
||||
_pointOfCareRepositoryMock.Object,
|
||||
new Lazy<IPatientService>(Mock.Of<IPatientService>),
|
||||
new Lazy<IUnitService>(() => _unitServiceMock.Object),
|
||||
Mock.Of<ISubscribersService>(),
|
||||
Mock.Of<Lazy<IClientMessageService>>(),
|
||||
new Lazy<IAdmissionService>(() => _admissionServiceMock.Object),
|
||||
_httpContextAccessorMock.Object,
|
||||
_auditServiceMock.Object,
|
||||
_cacheServiceMock.Object,
|
||||
Options.Create(new CacheSettings())
|
||||
);
|
||||
}
|
||||
|
||||
private PointOfCareService _pointOfCareService = null!;
|
||||
private Mock<IPointOfCareRepository> _pointOfCareRepositoryMock = null!;
|
||||
@@ -67,79 +72,98 @@ public class PointOfCareServiceTests
|
||||
private readonly Mock<IHttpContextAccessor> _httpContextAccessorMock = new();
|
||||
private readonly Mock<ILocalAuditService> _auditServiceMock = new();
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the <see cref="PointOfCareService.Delete"/> method successfully deletes a <c>PointOfCare</c>
|
||||
/// when invoked with a valid <see cref="ObjectId"/> whose associated admission is <c>null</c>, ensuring
|
||||
/// the underlying repository's delete operation is invoked.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Delete_ValidObjectId_DeletesPointOfCare()
|
||||
{
|
||||
// Arrange
|
||||
var id = ObjectId.GenerateNewId();
|
||||
_pointOfCareRepositoryMock.Setup(m => m.FindByIdAllConfig(id))
|
||||
.ReturnsAsync(new PointOfCare { Id = id, AdmissionId = null });
|
||||
_pointOfCareRepositoryMock.Setup(m => m.Delete(id)).Verifiable();
|
||||
|
||||
// Act
|
||||
await _pointOfCareService.Delete(id);
|
||||
|
||||
// Assert
|
||||
_pointOfCareRepositoryMock.Verify();
|
||||
}
|
||||
public async Task Delete_ValidObjectId_DeletesPointOfCare()
|
||||
{
|
||||
// Arrange
|
||||
var id = ObjectId.GenerateNewId();
|
||||
_pointOfCareRepositoryMock.Setup(m => m.FindByIdAllConfig(id))
|
||||
.ReturnsAsync(new PointOfCare { Id = id, AdmissionId = null });
|
||||
_pointOfCareRepositoryMock.Setup(m => m.Delete(id)).Verifiable();
|
||||
|
||||
// Act
|
||||
await _pointOfCareService.Delete(id);
|
||||
|
||||
// Assert
|
||||
_pointOfCareRepositoryMock.Verify();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the <see cref="PointOfCareService.Update"/> method successfully updates a valid
|
||||
/// <see cref="PointOfCare"/> instance by delegating the operation to the underlying repository.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous test execution.</returns>
|
||||
[Test]
|
||||
public async Task Update_ValidPointOfCare_UpdatesPointOfCare()
|
||||
{
|
||||
// Arrange
|
||||
var pointOfCare = new PointOfCare { Id = ObjectId.GenerateNewId(), UnitName = "TestUnit" };
|
||||
_pointOfCareRepositoryMock.Setup(m => m.Update(pointOfCare)).Verifiable();
|
||||
|
||||
// Act
|
||||
await _pointOfCareService.Update(pointOfCare);
|
||||
|
||||
// Assert
|
||||
_pointOfCareRepositoryMock.Verify();
|
||||
}
|
||||
public async Task Update_ValidPointOfCare_UpdatesPointOfCare()
|
||||
{
|
||||
// Arrange
|
||||
var pointOfCare = new PointOfCare { Id = ObjectId.GenerateNewId(), UnitName = "TestUnit" };
|
||||
_pointOfCareRepositoryMock.Setup(m => m.Update(pointOfCare)).Verifiable();
|
||||
|
||||
// Act
|
||||
await _pointOfCareService.Update(pointOfCare);
|
||||
|
||||
// Assert
|
||||
_pointOfCareRepositoryMock.Verify();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="PointOfCareService.GetAll"/> returns the complete list of point of care records provided by the repository when invoked with no arguments.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetAll_NoArguments_ReturnsListOfPointOfCare()
|
||||
{
|
||||
// Arrange
|
||||
var pointOfCareList = new List<PointOfCare> { new(), new() };
|
||||
_pointOfCareRepositoryMock.Setup(m => m.GetAll()).ReturnsAsync(pointOfCareList);
|
||||
|
||||
// Act
|
||||
var result = await _pointOfCareService.GetAll();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(pointOfCareList));
|
||||
}
|
||||
public async Task GetAll_NoArguments_ReturnsListOfPointOfCare()
|
||||
{
|
||||
// Arrange
|
||||
var pointOfCareList = new List<PointOfCare> { new(), new() };
|
||||
_pointOfCareRepositoryMock.Setup(m => m.GetAll()).ReturnsAsync(pointOfCareList);
|
||||
|
||||
// Act
|
||||
var result = await _pointOfCareService.GetAll();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(pointOfCareList));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="PointOfCareService.UpdateConfiguration"/> throws a <see cref="ConflictException"/> when invoked with a valid id and configuration, ensuring the service surfaces conflict conditions during the update operation.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void UpdateConfiguration_ValidIdAndConfiguration_InvokesRepositoryUpdateConfiguration()
|
||||
{
|
||||
// Arrange
|
||||
var id = ObjectId.GenerateNewId();
|
||||
var configuration = new PointOfCareConfiguration();
|
||||
|
||||
// Act & Assert
|
||||
Assert.That(_pointOfCareService, Is.Not.Null);
|
||||
Assert.That(_pointOfCareRepositoryMock, Is.Not.Null);
|
||||
|
||||
Func<Task> act = async () => await _pointOfCareService.UpdateConfiguration(id, configuration);
|
||||
Assert.ThrowsAsync<ConflictException>(act);
|
||||
}
|
||||
public void UpdateConfiguration_ValidIdAndConfiguration_InvokesRepositoryUpdateConfiguration()
|
||||
{
|
||||
// Arrange
|
||||
var id = ObjectId.GenerateNewId();
|
||||
var configuration = new PointOfCareConfiguration();
|
||||
|
||||
// Act & Assert
|
||||
Assert.That(_pointOfCareService, Is.Not.Null);
|
||||
Assert.That(_pointOfCareRepositoryMock, Is.Not.Null);
|
||||
|
||||
Func<Task> act = async () => await _pointOfCareService.UpdateConfiguration(id, configuration);
|
||||
Assert.ThrowsAsync<ConflictException>(act);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>FindById</c> returns the expected <see cref="PointOfCare"/> when a valid identifier is provided.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindById_ValidId_ReturnsPointOfCare()
|
||||
{
|
||||
// Arrange
|
||||
var id = ObjectId.GenerateNewId();
|
||||
var expectedPointOfCare = new PointOfCare { Id = id };
|
||||
_pointOfCareRepositoryMock.Setup(m => m.FindByIdAllConfig(id)).ReturnsAsync(expectedPointOfCare);
|
||||
|
||||
// Act
|
||||
var result = await _pointOfCareService.FindById(id);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(expectedPointOfCare));
|
||||
}
|
||||
public async Task FindById_ValidId_ReturnsPointOfCare()
|
||||
{
|
||||
// Arrange
|
||||
var id = ObjectId.GenerateNewId();
|
||||
var expectedPointOfCare = new PointOfCare { Id = id };
|
||||
_pointOfCareRepositoryMock.Setup(m => m.FindByIdAllConfig(id)).ReturnsAsync(expectedPointOfCare);
|
||||
|
||||
// Act
|
||||
var result = await _pointOfCareService.FindById(id);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(expectedPointOfCare));
|
||||
}
|
||||
|
||||
// [Test]
|
||||
// public async Task FindByUnit_ValidUnit_ReturnsListOfPointOfCare()
|
||||
@@ -162,26 +186,29 @@ public class PointOfCareServiceTests
|
||||
// Assert.That(result, Is.EqualTo(expectedPointOfCareList));
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="PointOfCareService.FindByUnitAndStatus"/> returns the expected list of point-of-care records when invoked with a valid unit identifier and status.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByUnitAndStatus_ValidUnitIdAndStatus_ReturnsListOfPointOfCare()
|
||||
{
|
||||
// Arrange
|
||||
var unitId = ObjectId.GenerateNewId();
|
||||
var pocStatus = StatusEnum.PointOfCare.Available;
|
||||
var expectedPointOfCareList = new List<PointOfCare>
|
||||
public async Task FindByUnitAndStatus_ValidUnitIdAndStatus_ReturnsListOfPointOfCare()
|
||||
{
|
||||
new(),
|
||||
new()
|
||||
};
|
||||
_pointOfCareRepositoryMock.Setup(m => m.FindByUnitAndStatus(unitId, pocStatus, false))
|
||||
.ReturnsAsync(expectedPointOfCareList);
|
||||
|
||||
// Act
|
||||
var result = await _pointOfCareService.FindByUnitAndStatus(unitId, pocStatus);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(expectedPointOfCareList));
|
||||
}
|
||||
// Arrange
|
||||
var unitId = ObjectId.GenerateNewId();
|
||||
var pocStatus = StatusEnum.PointOfCare.Available;
|
||||
var expectedPointOfCareList = new List<PointOfCare>
|
||||
{
|
||||
new(),
|
||||
new()
|
||||
};
|
||||
_pointOfCareRepositoryMock.Setup(m => m.FindByUnitAndStatus(unitId, pocStatus, false))
|
||||
.ReturnsAsync(expectedPointOfCareList);
|
||||
|
||||
// Act
|
||||
var result = await _pointOfCareService.FindByUnitAndStatus(unitId, pocStatus);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(expectedPointOfCareList));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckNextAdmission_ValidPatientLocation_UpdatesPoCStatus_AndCallsUpdate()
|
||||
@@ -256,36 +283,42 @@ public class PointOfCareServiceTests
|
||||
// c) NO verifiques FindByIdAllConfig: en CheckNextAdmission no se usa esa ruta
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that the service's FindByRoom method, when called with a valid room, returns the collection provided by the repository and invokes the repository's FindByRoom exactly once.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByRoom_ValidRoom_CallsRepositoryFindByRoom()
|
||||
{
|
||||
// Arrange
|
||||
const string room = "TestRoom";
|
||||
var expectedPointOfCares = new List<PointOfCare>();
|
||||
_pointOfCareRepositoryMock.Setup(m => m.FindByRoom(room)).ReturnsAsync(expectedPointOfCares);
|
||||
|
||||
// Act
|
||||
var result = await _pointOfCareService.FindByRoom(room);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(expectedPointOfCares));
|
||||
_pointOfCareRepositoryMock.Verify(m => m.FindByRoom(room), Times.Once);
|
||||
}
|
||||
public async Task FindByRoom_ValidRoom_CallsRepositoryFindByRoom()
|
||||
{
|
||||
// Arrange
|
||||
const string room = "TestRoom";
|
||||
var expectedPointOfCares = new List<PointOfCare>();
|
||||
_pointOfCareRepositoryMock.Setup(m => m.FindByRoom(room)).ReturnsAsync(expectedPointOfCares);
|
||||
|
||||
// Act
|
||||
var result = await _pointOfCareService.FindByRoom(room);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(expectedPointOfCares));
|
||||
_pointOfCareRepositoryMock.Verify(m => m.FindByRoom(room), Times.Once);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the <see cref="PointOfCareService.FindByBed"/> method correctly delegates to the repository's FindByBed method when a valid bed identifier is provided, returning the expected collection of point of care records.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByBed_ValidBed_CallsRepositoryFindByBed()
|
||||
{
|
||||
// Arrange
|
||||
const string bed = "TestBed";
|
||||
var expectedPointOfCares = new List<PointOfCare>();
|
||||
_pointOfCareRepositoryMock.Setup(m => m.FindByBed(bed)).ReturnsAsync(expectedPointOfCares);
|
||||
|
||||
// Act
|
||||
var result = await _pointOfCareService.FindByBed(bed);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(expectedPointOfCares));
|
||||
_pointOfCareRepositoryMock.Verify(m => m.FindByBed(bed), Times.Once);
|
||||
}
|
||||
public async Task FindByBed_ValidBed_CallsRepositoryFindByBed()
|
||||
{
|
||||
// Arrange
|
||||
const string bed = "TestBed";
|
||||
var expectedPointOfCares = new List<PointOfCare>();
|
||||
_pointOfCareRepositoryMock.Setup(m => m.FindByBed(bed)).ReturnsAsync(expectedPointOfCares);
|
||||
|
||||
// Act
|
||||
var result = await _pointOfCareService.FindByBed(bed);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(expectedPointOfCares));
|
||||
_pointOfCareRepositoryMock.Verify(m => m.FindByBed(bed), Times.Once);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,19 +14,22 @@ public class PublisherServiceTest
|
||||
//private static readonly DateTime now = DateTime.Now;
|
||||
//private static readonly ObjectId patientId = ObjectId.GenerateNewId();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the test environment for <see cref="PublisherService"/> by configuring RabbitMQ settings, creating a mocked logger, and instantiating the service under test.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
//advancedBusMock = new Mock<IAdvancedBus>();
|
||||
|
||||
_optionsRabbitMqSettings = Options.Create(_rabbitMqSettings);
|
||||
|
||||
_logger = new Mock<ILogger<PublisherService>>();
|
||||
|
||||
_publisherService = new PublisherService(
|
||||
_optionsRabbitMqSettings,
|
||||
_logger.Object);
|
||||
}
|
||||
public void Setup()
|
||||
{
|
||||
//advancedBusMock = new Mock<IAdvancedBus>();
|
||||
|
||||
_optionsRabbitMqSettings = Options.Create(_rabbitMqSettings);
|
||||
|
||||
_logger = new Mock<ILogger<PublisherService>>();
|
||||
|
||||
_publisherService = new PublisherService(
|
||||
_optionsRabbitMqSettings,
|
||||
_logger.Object);
|
||||
}
|
||||
|
||||
private PublisherService _publisherService = null!;
|
||||
//private Mock<IAdvancedBus> advancedBusMock;
|
||||
@@ -40,23 +43,29 @@ public class PublisherServiceTest
|
||||
|
||||
private Mock<ILogger<PublisherService>> _logger = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the publisher service's SendMessage method returns a non-null result when sending a message to the observations queue.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void SendMessage_Return_true()
|
||||
{
|
||||
var newMessage = new Message<string>();
|
||||
|
||||
var result = _publisherService.SendMessage(newMessage, _rabbitMqSettings.ObservationsQueue);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
public void SendMessage_Return_true()
|
||||
{
|
||||
var newMessage = new Message<string>();
|
||||
|
||||
var result = _publisherService.SendMessage(newMessage, _rabbitMqSettings.ObservationsQueue);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>SendMessageError</c> returns a non-null result when publishing a new <see cref="Message{Error}"/> to the observations queue.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void SendMessage_Error_Return_true()
|
||||
{
|
||||
var newMessage = new Message<Error>();
|
||||
|
||||
var result = _publisherService.SendMessageError(newMessage, _rabbitMqSettings.ObservationsQueue);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
public void SendMessage_Error_Return_true()
|
||||
{
|
||||
var newMessage = new Message<Error>();
|
||||
|
||||
var result = _publisherService.SendMessageError(newMessage, _rabbitMqSettings.ObservationsQueue);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
}
|
||||
@@ -40,224 +40,258 @@ public class PumpServiceTest
|
||||
private static readonly ObjectId PatientId = ObjectId.GenerateNewId();
|
||||
private static readonly DateTime Now = DateTime.UtcNow;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the unit test fixture by creating mock repositories, services, and a mocked <see cref="HttpContext"/> with a test claims principal, then instantiates the <see cref="PumpService"/> under test using the configured API settings (5-second pump expiration, zero pump messages disabled). Pass-through mappings are configured for <see cref="ICalculatedObservationsService"/>, <see cref="IConfigPumpsService"/>, and <see cref="IConfigUnitsService"/> so that supplied pump observations are returned unchanged.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_obsRepo = new Mock<IPumpObservationRepository>();
|
||||
_stateRepo = new Mock<IPumpStateRepository>();
|
||||
_alarmEventRepo = new Mock<IPumpAlarmEventRepository>();
|
||||
_alarmStateRepo = new Mock<IPumpAlarmStateRepository>();
|
||||
_archiveRepo = new Mock<IPumpArchiveRepository>();
|
||||
_patientSvc = new Mock<IPatientService>();
|
||||
_configPumps = new Mock<IConfigPumpsService>();
|
||||
_subs = new Mock<ISubscribersService>();
|
||||
_clientMsg = new Mock<IClientMessageService>();
|
||||
_calcObs = new Mock<ICalculatedObservationsService>();
|
||||
_lazyCalc = new Lazy<ICalculatedObservationsService>(() => _calcObs.Object);
|
||||
_http = new Mock<IHttpContextAccessor>();
|
||||
_audit = new Mock<ILocalAuditService>();
|
||||
_logger = new Mock<ILogger<PumpService>>();
|
||||
_configUnits = new Mock<IConfigUnitsService>();
|
||||
|
||||
var principal = new ClaimsPrincipal(
|
||||
new ClaimsIdentity([new Claim(ClaimTypes.Name, "test")], "mock"));
|
||||
|
||||
_http.Setup(x => x.HttpContext)
|
||||
.Returns(new DefaultHttpContext { User = principal });
|
||||
|
||||
_calcObs.Setup(x => x.Map(It.IsAny<PumpObservation>()))
|
||||
.ReturnsAsync((PumpObservation o) => o);
|
||||
|
||||
var api = Options.Create(new ApiSettings
|
||||
public void Setup()
|
||||
{
|
||||
PumpExpiresSeconds = 5,
|
||||
SendPumpsZero = false
|
||||
});
|
||||
|
||||
_service = new PumpService(
|
||||
_obsRepo.Object,
|
||||
_stateRepo.Object,
|
||||
_alarmEventRepo.Object,
|
||||
_alarmStateRepo.Object,
|
||||
_archiveRepo.Object,
|
||||
_patientSvc.Object,
|
||||
_configPumps.Object,
|
||||
api,
|
||||
_logger.Object,
|
||||
_subs.Object,
|
||||
_clientMsg.Object,
|
||||
_lazyCalc,
|
||||
_http.Object,
|
||||
_audit.Object,
|
||||
_configUnits.Object
|
||||
);
|
||||
|
||||
_configPumps.Setup(x => x.Map(It.IsAny<PumpObservation>()))
|
||||
.ReturnsAsync((PumpObservation o) => o);
|
||||
_configUnits.Setup(x => x.Map(It.IsAny<PumpObservation>()))
|
||||
.ReturnsAsync((PumpObservation o) => o);
|
||||
}
|
||||
_obsRepo = new Mock<IPumpObservationRepository>();
|
||||
_stateRepo = new Mock<IPumpStateRepository>();
|
||||
_alarmEventRepo = new Mock<IPumpAlarmEventRepository>();
|
||||
_alarmStateRepo = new Mock<IPumpAlarmStateRepository>();
|
||||
_archiveRepo = new Mock<IPumpArchiveRepository>();
|
||||
_patientSvc = new Mock<IPatientService>();
|
||||
_configPumps = new Mock<IConfigPumpsService>();
|
||||
_subs = new Mock<ISubscribersService>();
|
||||
_clientMsg = new Mock<IClientMessageService>();
|
||||
_calcObs = new Mock<ICalculatedObservationsService>();
|
||||
_lazyCalc = new Lazy<ICalculatedObservationsService>(() => _calcObs.Object);
|
||||
_http = new Mock<IHttpContextAccessor>();
|
||||
_audit = new Mock<ILocalAuditService>();
|
||||
_logger = new Mock<ILogger<PumpService>>();
|
||||
_configUnits = new Mock<IConfigUnitsService>();
|
||||
|
||||
var principal = new ClaimsPrincipal(
|
||||
new ClaimsIdentity([new Claim(ClaimTypes.Name, "test")], "mock"));
|
||||
|
||||
_http.Setup(x => x.HttpContext)
|
||||
.Returns(new DefaultHttpContext { User = principal });
|
||||
|
||||
_calcObs.Setup(x => x.Map(It.IsAny<PumpObservation>()))
|
||||
.ReturnsAsync((PumpObservation o) => o);
|
||||
|
||||
var api = Options.Create(new ApiSettings
|
||||
{
|
||||
PumpExpiresSeconds = 5,
|
||||
SendPumpsZero = false
|
||||
});
|
||||
|
||||
_service = new PumpService(
|
||||
_obsRepo.Object,
|
||||
_stateRepo.Object,
|
||||
_alarmEventRepo.Object,
|
||||
_alarmStateRepo.Object,
|
||||
_archiveRepo.Object,
|
||||
_patientSvc.Object,
|
||||
_configPumps.Object,
|
||||
api,
|
||||
_logger.Object,
|
||||
_subs.Object,
|
||||
_clientMsg.Object,
|
||||
_lazyCalc,
|
||||
_http.Object,
|
||||
_audit.Object,
|
||||
_configUnits.Object
|
||||
);
|
||||
|
||||
_configPumps.Setup(x => x.Map(It.IsAny<PumpObservation>()))
|
||||
.ReturnsAsync((PumpObservation o) => o);
|
||||
_configUnits.Setup(x => x.Map(It.IsAny<PumpObservation>()))
|
||||
.ReturnsAsync((PumpObservation o) => o);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// SAVE REQUEST — casos básicos
|
||||
// --------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="ApiRequest"/> processing does not insert any <see cref="PumpObservation"/> records
|
||||
/// when the request is saved without associated observations.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task SaveRequest_Returns_When_No_Observations()
|
||||
{
|
||||
var req = new ApiRequest { Type = "ORU_R01" };
|
||||
await _service.SaveRequest(req);
|
||||
_obsRepo.Verify(r => r.InsertAsync(It.IsAny<PumpObservation>()), Times.Never);
|
||||
}
|
||||
public async Task SaveRequest_Returns_When_No_Observations()
|
||||
{
|
||||
var req = new ApiRequest { Type = "ORU_R01" };
|
||||
await _service.SaveRequest(req);
|
||||
_obsRepo.Verify(r => r.InsertAsync(It.IsAny<PumpObservation>()), Times.Never);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>SaveRequest</c> does not insert a <see cref="PumpObservation"/> when the <see cref="ApiRequest.Type"/> is an unrecognized value.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task SaveRequest_UnknownType_DoesNotInsert()
|
||||
{
|
||||
var req = new ApiRequest
|
||||
public async Task SaveRequest_UnknownType_DoesNotInsert()
|
||||
{
|
||||
Type = "UNKNOWN",
|
||||
PumpObservation = new PumpObservation { Time = Now }
|
||||
};
|
||||
|
||||
await _service.SaveRequest(req);
|
||||
_obsRepo.Verify(r => r.InsertAsync(It.IsAny<PumpObservation>()), Times.Never);
|
||||
}
|
||||
var req = new ApiRequest
|
||||
{
|
||||
Type = "UNKNOWN",
|
||||
PumpObservation = new PumpObservation { Time = Now }
|
||||
};
|
||||
|
||||
await _service.SaveRequest(req);
|
||||
_obsRepo.Verify(r => r.InsertAsync(It.IsAny<PumpObservation>()), Times.Never);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that SaveRequest converts a single <c>PumpObservation</c> on an incoming
|
||||
/// <c>ApiRequest</c> into a list with one entry on the request after processing.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task SaveRequest_Converts_SingleObservation_ToList()
|
||||
{
|
||||
var obs = new PumpObservation { Time = Now };
|
||||
var req = new ApiRequest
|
||||
public async Task SaveRequest_Converts_SingleObservation_ToList()
|
||||
{
|
||||
Type = "ORU_R01",
|
||||
PumpObservation = obs,
|
||||
PatientNumber = "123"
|
||||
};
|
||||
|
||||
_patientSvc.Setup(p => p.FindPatientByApiRequest(req))
|
||||
.ReturnsAsync(new Patient { Id = PatientId });
|
||||
|
||||
await _service.SaveRequest(req);
|
||||
Assert.That(req.PumpObservations, Has.Count.EqualTo(1));
|
||||
}
|
||||
var obs = new PumpObservation { Time = Now };
|
||||
var req = new ApiRequest
|
||||
{
|
||||
Type = "ORU_R01",
|
||||
PumpObservation = obs,
|
||||
PatientNumber = "123"
|
||||
};
|
||||
|
||||
_patientSvc.Setup(p => p.FindPatientByApiRequest(req))
|
||||
.ReturnsAsync(new Patient { Id = PatientId });
|
||||
|
||||
await _service.SaveRequest(req);
|
||||
Assert.That(req.PumpObservations, Has.Count.EqualTo(1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that Service.SaveRequest sets the <c>Expires</c> property of the <see cref="PumpObservation"/> before persisting it via the repository.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task SaveRequest_SetsExpires_BeforeInsert()
|
||||
{
|
||||
var obs = new PumpObservation
|
||||
public async Task SaveRequest_SetsExpires_BeforeInsert()
|
||||
{
|
||||
Time = Now,
|
||||
DeviceId = "D1"
|
||||
};
|
||||
|
||||
var req = new ApiRequest
|
||||
{
|
||||
Type = "ORU_R01",
|
||||
PumpObservation = obs,
|
||||
PatientNumber = "1"
|
||||
};
|
||||
|
||||
_patientSvc.Setup(x => x.FindPatientByApiRequest(req))
|
||||
.ReturnsAsync(new Patient { Id = PatientId });
|
||||
|
||||
await _service.SaveRequest(req);
|
||||
|
||||
_obsRepo.Verify(r => r.InsertAsync(
|
||||
It.Is<PumpObservation>(o => o.Expires == 5)), Times.Once);
|
||||
}
|
||||
var obs = new PumpObservation
|
||||
{
|
||||
Time = Now,
|
||||
DeviceId = "D1"
|
||||
};
|
||||
|
||||
var req = new ApiRequest
|
||||
{
|
||||
Type = "ORU_R01",
|
||||
PumpObservation = obs,
|
||||
PatientNumber = "1"
|
||||
};
|
||||
|
||||
_patientSvc.Setup(x => x.FindPatientByApiRequest(req))
|
||||
.ReturnsAsync(new Patient { Id = PatientId });
|
||||
|
||||
await _service.SaveRequest(req);
|
||||
|
||||
_obsRepo.Verify(r => r.InsertAsync(
|
||||
It.Is<PumpObservation>(o => o.Expires == 5)), Times.Once);
|
||||
}
|
||||
// --------------------------------------------------------------
|
||||
// PROCESS ALARM
|
||||
// --------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that saving a request of type "ORU_R40" creates a <see cref="PumpAlarmEvent"/>
|
||||
/// and does not create a <see cref="PumpObservation"/>, ensuring alarm-phase events are
|
||||
/// routed to the alarm event store rather than the observation store.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task SaveRequest_ORU_R40_CreatesAlarmEvent()
|
||||
{
|
||||
var obs = new PumpObservation
|
||||
public async Task SaveRequest_ORU_R40_CreatesAlarmEvent()
|
||||
{
|
||||
Time = Now,
|
||||
DeviceId = "D1",
|
||||
AlarmType = PumpEnum.AlarmType.Occlusion,
|
||||
EventPhase = PumpEnum.EventPhase.Start
|
||||
};
|
||||
|
||||
var req = new ApiRequest { Type = "ORU_R40", PumpObservation = obs };
|
||||
_patientSvc.Setup(x => x.FindPatientByApiRequest(req))
|
||||
.ReturnsAsync(new Patient { Id = PatientId });
|
||||
|
||||
await _service.SaveRequest(req);
|
||||
|
||||
_alarmEventRepo.Verify(r => r.InsertAsync(It.IsAny<PumpAlarmEvent>()), Times.Once);
|
||||
_obsRepo.Verify(r => r.InsertAsync(It.IsAny<PumpObservation>()), Times.Never);
|
||||
}
|
||||
var obs = new PumpObservation
|
||||
{
|
||||
Time = Now,
|
||||
DeviceId = "D1",
|
||||
AlarmType = PumpEnum.AlarmType.Occlusion,
|
||||
EventPhase = PumpEnum.EventPhase.Start
|
||||
};
|
||||
|
||||
var req = new ApiRequest { Type = "ORU_R40", PumpObservation = obs };
|
||||
_patientSvc.Setup(x => x.FindPatientByApiRequest(req))
|
||||
.ReturnsAsync(new Patient { Id = PatientId });
|
||||
|
||||
await _service.SaveRequest(req);
|
||||
|
||||
_alarmEventRepo.Verify(r => r.InsertAsync(It.IsAny<PumpAlarmEvent>()), Times.Once);
|
||||
_obsRepo.Verify(r => r.InsertAsync(It.IsAny<PumpObservation>()), Times.Never);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that processing a pump observation with <c>EventPhase.End</c> removes the corresponding alarm state
|
||||
/// by calling <c>RemoveAsync</c> on the alarm state repository with the matching device, alarm type, and MDC code.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ProcessAlarm_End_RemovesAlarmState()
|
||||
{
|
||||
var obs = new PumpObservation
|
||||
public async Task ProcessAlarm_End_RemovesAlarmState()
|
||||
{
|
||||
Time = Now,
|
||||
DeviceId = "DX",
|
||||
AlarmType = PumpEnum.AlarmType.Occlusion,
|
||||
AlarmTypeMdc = "H1",
|
||||
EventPhase = PumpEnum.EventPhase.End
|
||||
};
|
||||
|
||||
var req = new ApiRequest { Type = "ORU_R40", PumpObservation = obs };
|
||||
_patientSvc.Setup(x => x.FindPatientByApiRequest(req))
|
||||
.ReturnsAsync(new Patient { Id = PatientId });
|
||||
|
||||
await _service.SaveRequest(req);
|
||||
|
||||
_alarmStateRepo.Verify(r => r.RemoveAsync("DX", PumpEnum.AlarmType.Occlusion, "H1"), Times.Once);
|
||||
}
|
||||
var obs = new PumpObservation
|
||||
{
|
||||
Time = Now,
|
||||
DeviceId = "DX",
|
||||
AlarmType = PumpEnum.AlarmType.Occlusion,
|
||||
AlarmTypeMdc = "H1",
|
||||
EventPhase = PumpEnum.EventPhase.End
|
||||
};
|
||||
|
||||
var req = new ApiRequest { Type = "ORU_R40", PumpObservation = obs };
|
||||
_patientSvc.Setup(x => x.FindPatientByApiRequest(req))
|
||||
.ReturnsAsync(new Patient { Id = PatientId });
|
||||
|
||||
await _service.SaveRequest(req);
|
||||
|
||||
_alarmStateRepo.Verify(r => r.RemoveAsync("DX", PumpEnum.AlarmType.Occlusion, "H1"), Times.Once);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// SNAPSHOT DE BOMBA
|
||||
// --------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that <c>SaveRequest</c> creates and upserts a new <see cref="PumpState"/>
|
||||
/// for the device when no existing pump state is found in the repository.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task SaveRequest_CreatesPumpState_IfNotExists()
|
||||
{
|
||||
var obs = new PumpObservation { Time = Now, DeviceId = "P1" };
|
||||
var req = new ApiRequest { Type = "ORU_R01", PumpObservation = obs, PatientNumber = "1" };
|
||||
|
||||
_patientSvc.Setup(x => x.FindPatientByApiRequest(req))
|
||||
.ReturnsAsync(new Patient { Id = PatientId });
|
||||
|
||||
_stateRepo.Setup(r => r.FindByDeviceIdAsync("P1"))
|
||||
.ReturnsAsync((PumpState?)null);
|
||||
|
||||
await _service.SaveRequest(req);
|
||||
|
||||
_stateRepo.Verify(r => r.UpsertAsync(It.Is<PumpState>(s => s.DeviceId == "P1")), Times.Once);
|
||||
}
|
||||
public async Task SaveRequest_CreatesPumpState_IfNotExists()
|
||||
{
|
||||
var obs = new PumpObservation { Time = Now, DeviceId = "P1" };
|
||||
var req = new ApiRequest { Type = "ORU_R01", PumpObservation = obs, PatientNumber = "1" };
|
||||
|
||||
_patientSvc.Setup(x => x.FindPatientByApiRequest(req))
|
||||
.ReturnsAsync(new Patient { Id = PatientId });
|
||||
|
||||
_stateRepo.Setup(r => r.FindByDeviceIdAsync("P1"))
|
||||
.ReturnsAsync((PumpState?)null);
|
||||
|
||||
await _service.SaveRequest(req);
|
||||
|
||||
_stateRepo.Verify(r => r.UpsertAsync(It.Is<PumpState>(s => s.DeviceId == "P1")), Times.Once);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// BROADCAST
|
||||
// --------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that SaveRequest does not broadcast a message via the client when there are no active subscribers.
|
||||
/// </summary>
|
||||
/// <returns>A task that completes when the assertion has been executed.</returns>
|
||||
[Test]
|
||||
public async Task SaveRequest_NoSubscribers_NoBroadcast()
|
||||
{
|
||||
var obs = new PumpObservation { Time = Now, DeviceId = "BR1", PatientId = PatientId };
|
||||
var patient = new Patient
|
||||
public async Task SaveRequest_NoSubscribers_NoBroadcast()
|
||||
{
|
||||
Id = PatientId,
|
||||
Location = new PatientLocation("U1", "B1")
|
||||
};
|
||||
|
||||
var req = new ApiRequest
|
||||
{
|
||||
Type = "ORU_R01",
|
||||
PumpObservation = obs,
|
||||
PatientNumber = "1"
|
||||
};
|
||||
|
||||
_subs.Setup(x => x.GetSubscribers()).Returns([]);
|
||||
_patientSvc.Setup(x => x.FindPatientByApiRequest(req))
|
||||
.ReturnsAsync(patient);
|
||||
|
||||
await _service.SaveRequest(req);
|
||||
|
||||
_clientMsg.Verify(r => r.SendAsync(It.IsAny<string>(), It.IsAny<OperationType>(), It.IsAny<object>()),
|
||||
Times.Never);
|
||||
}
|
||||
var obs = new PumpObservation { Time = Now, DeviceId = "BR1", PatientId = PatientId };
|
||||
var patient = new Patient
|
||||
{
|
||||
Id = PatientId,
|
||||
Location = new PatientLocation("U1", "B1")
|
||||
};
|
||||
|
||||
var req = new ApiRequest
|
||||
{
|
||||
Type = "ORU_R01",
|
||||
PumpObservation = obs,
|
||||
PatientNumber = "1"
|
||||
};
|
||||
|
||||
_subs.Setup(x => x.GetSubscribers()).Returns([]);
|
||||
_patientSvc.Setup(x => x.FindPatientByApiRequest(req))
|
||||
.ReturnsAsync(patient);
|
||||
|
||||
await _service.SaveRequest(req);
|
||||
|
||||
_clientMsg.Verify(r => r.SendAsync(It.IsAny<string>(), It.IsAny<OperationType>(), It.IsAny<object>()),
|
||||
Times.Never);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task SaveRequest_WithSubscribers_UsesReqLocation_AndSendsBroadcast()
|
||||
@@ -322,140 +356,165 @@ public class PumpServiceTest
|
||||
// --------------------------------------------------------------
|
||||
// RETENCIÓN — DeleteOlderDays
|
||||
// --------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that <c>SaveRequest</c> invokes the observation repository's
|
||||
/// <c>DeleteOlderThanDaysAsync</c> method with the configured retention value when the
|
||||
/// retention policy returned for the pump observation is <c>DeleteOlderDays</c>.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task SaveRequest_Retention_DeleteOlderDays_CallsRepo()
|
||||
{
|
||||
var obs = new PumpObservation { Time = Now, DeviceId = "R1", PatientId = PatientId };
|
||||
var req = new ApiRequest { Type = "ORU_R01", PumpObservation = obs, PatientNumber = "1" };
|
||||
|
||||
_patientSvc.Setup(x => x.FindPatientByApiRequest(req))
|
||||
.ReturnsAsync(new Patient { Id = PatientId });
|
||||
|
||||
_configPumps.Setup(x => x.RetentionActions(It.IsAny<PumpObservation>()))
|
||||
.ReturnsAsync(new ObservatitonRetentionResult
|
||||
{
|
||||
RetentionPolicy = RetentionPolicy.DeleteOlderDays,
|
||||
RetentionPolicyValue = 7
|
||||
});
|
||||
|
||||
await _service.SaveRequest(req);
|
||||
|
||||
_obsRepo.Verify(r => r.DeleteOlderThanDaysAsync(7, null), Times.Once);
|
||||
}
|
||||
public async Task SaveRequest_Retention_DeleteOlderDays_CallsRepo()
|
||||
{
|
||||
var obs = new PumpObservation { Time = Now, DeviceId = "R1", PatientId = PatientId };
|
||||
var req = new ApiRequest { Type = "ORU_R01", PumpObservation = obs, PatientNumber = "1" };
|
||||
|
||||
_patientSvc.Setup(x => x.FindPatientByApiRequest(req))
|
||||
.ReturnsAsync(new Patient { Id = PatientId });
|
||||
|
||||
_configPumps.Setup(x => x.RetentionActions(It.IsAny<PumpObservation>()))
|
||||
.ReturnsAsync(new ObservatitonRetentionResult
|
||||
{
|
||||
RetentionPolicy = RetentionPolicy.DeleteOlderDays,
|
||||
RetentionPolicyValue = 7
|
||||
});
|
||||
|
||||
await _service.SaveRequest(req);
|
||||
|
||||
_obsRepo.Verify(r => r.DeleteOlderThanDaysAsync(7, null), Times.Once);
|
||||
}
|
||||
// --------------------------------------------------------------
|
||||
// PAGINACIÓN
|
||||
// --------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that <c>GetPaginatedPump</c> returns the correct paginated results when filtering by patient identifier.
|
||||
/// Ensures the first page contains the most recent observation within the configured time tolerance.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetPaginatedPump_ByPatient_Works()
|
||||
{
|
||||
var obs = new List<PumpObservation>
|
||||
public async Task GetPaginatedPump_ByPatient_Works()
|
||||
{
|
||||
new() { Time = Now.AddMinutes(-1), PatientId = PatientId },
|
||||
new() { Time = Now.AddMinutes(-5), PatientId = PatientId }
|
||||
};
|
||||
|
||||
_obsRepo.Setup(r => r.FindByPatientId(PatientId))
|
||||
.ReturnsAsync(obs);
|
||||
|
||||
var fileredRequest = new FilteredRequest
|
||||
{
|
||||
PatientId = PatientId.ToString()
|
||||
};
|
||||
|
||||
var filter = new PaginationFilter(1, 1, fileredRequest);
|
||||
|
||||
var result = await _service.GetPaginatedPump(filter);
|
||||
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(result!.Data, Has.Count.EqualTo(1));
|
||||
Assert.That(result.Data[0].Time, Is.EqualTo(Now.AddMinutes(-1)).Within(TimeSpan.FromMilliseconds(2)));
|
||||
var obs = new List<PumpObservation>
|
||||
{
|
||||
new() { Time = Now.AddMinutes(-1), PatientId = PatientId },
|
||||
new() { Time = Now.AddMinutes(-5), PatientId = PatientId }
|
||||
};
|
||||
|
||||
_obsRepo.Setup(r => r.FindByPatientId(PatientId))
|
||||
.ReturnsAsync(obs);
|
||||
|
||||
var fileredRequest = new FilteredRequest
|
||||
{
|
||||
PatientId = PatientId.ToString()
|
||||
};
|
||||
|
||||
var filter = new PaginationFilter(1, 1, fileredRequest);
|
||||
|
||||
var result = await _service.GetPaginatedPump(filter);
|
||||
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(result!.Data, Has.Count.EqualTo(1));
|
||||
Assert.That(result.Data[0].Time, Is.EqualTo(Now.AddMinutes(-1)).Within(TimeSpan.FromMilliseconds(2)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// ARCHIVO
|
||||
// --------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that <c>ArchiveByPatientId</c> inserts the patient's pump observations into the archive
|
||||
/// repository and then deletes them, along with their related alarm events and alarm states.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ArchiveByPatientId_InsertsArchive_ThenDeletes()
|
||||
{
|
||||
var list = new List<PumpObservation>
|
||||
public async Task ArchiveByPatientId_InsertsArchive_ThenDeletes()
|
||||
{
|
||||
new() { Id = ObjectId.GenerateNewId(), PatientId = PatientId }
|
||||
};
|
||||
|
||||
_obsRepo.Setup(r => r.FindByPatientId(PatientId)).ReturnsAsync(list);
|
||||
|
||||
await _service.ArchiveByPatientId(PatientId);
|
||||
|
||||
_archiveRepo.Verify(r => r.InsertManyAsync(list), Times.Once);
|
||||
_obsRepo.Verify(r => r.DeleteByPatientId(PatientId), Times.Once);
|
||||
_alarmEventRepo.Verify(r => r.DeleteByPatientId(PatientId), Times.Once);
|
||||
_alarmStateRepo.Verify(r => r.DeleteByPatientId(PatientId), Times.Once);
|
||||
}
|
||||
var list = new List<PumpObservation>
|
||||
{
|
||||
new() { Id = ObjectId.GenerateNewId(), PatientId = PatientId }
|
||||
};
|
||||
|
||||
_obsRepo.Setup(r => r.FindByPatientId(PatientId)).ReturnsAsync(list);
|
||||
|
||||
await _service.ArchiveByPatientId(PatientId);
|
||||
|
||||
_archiveRepo.Verify(r => r.InsertManyAsync(list), Times.Once);
|
||||
_obsRepo.Verify(r => r.DeleteByPatientId(PatientId), Times.Once);
|
||||
_alarmEventRepo.Verify(r => r.DeleteByPatientId(PatientId), Times.Once);
|
||||
_alarmStateRepo.Verify(r => r.DeleteByPatientId(PatientId), Times.Once);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// UPDATE MANY
|
||||
// --------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that <c>UpdateManyObjectId</c> correctly updates the patient identifier across observations, alarms, and alarm state repositories.
|
||||
/// </summary>
|
||||
/// <returns>A task representing the asynchronous test execution.</returns>
|
||||
[Test]
|
||||
public async Task UpdateManyObjectId_UpdatesObs_Alarms_States()
|
||||
{
|
||||
var oldId = ObjectId.GenerateNewId();
|
||||
var newId = ObjectId.GenerateNewId();
|
||||
|
||||
_obsRepo.Setup(r => r.UpdateManyObjectIdByFieldAsync("patientId", newId, oldId))
|
||||
.ReturnsAsync(3);
|
||||
_alarmEventRepo.Setup(r => r.UpdateManyObjectIdByFiledNameAsync("patientId", newId, oldId))
|
||||
.ReturnsAsync(1);
|
||||
_alarmStateRepo.Setup(r => r.UpdateManyObjectIdByFieldNameAsync("patientId", newId, oldId))
|
||||
.ReturnsAsync(2);
|
||||
|
||||
await _service.UpdateManyObjectId("patientId", newId, oldId);
|
||||
|
||||
}
|
||||
public async Task UpdateManyObjectId_UpdatesObs_Alarms_States()
|
||||
{
|
||||
var oldId = ObjectId.GenerateNewId();
|
||||
var newId = ObjectId.GenerateNewId();
|
||||
|
||||
_obsRepo.Setup(r => r.UpdateManyObjectIdByFieldAsync("patientId", newId, oldId))
|
||||
.ReturnsAsync(3);
|
||||
_alarmEventRepo.Setup(r => r.UpdateManyObjectIdByFiledNameAsync("patientId", newId, oldId))
|
||||
.ReturnsAsync(1);
|
||||
_alarmStateRepo.Setup(r => r.UpdateManyObjectIdByFieldNameAsync("patientId", newId, oldId))
|
||||
.ReturnsAsync(2);
|
||||
|
||||
await _service.UpdateManyObjectId("patientId", newId, oldId);
|
||||
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// FIND LAST OBSERVATIONS
|
||||
// --------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that <c>FindLastPumpObservations</c> returns pump observations ordered with the most recent first,
|
||||
/// returning only the specified number of latest entries when the repository provides multiple observations.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindLastPumpObservations_ReturnsOrdered()
|
||||
{
|
||||
var items = new List<PumpObservation>
|
||||
public async Task FindLastPumpObservations_ReturnsOrdered()
|
||||
{
|
||||
new() { Time = Now.AddMinutes(-10) },
|
||||
new() { Time = Now.AddMinutes(-1) }
|
||||
};
|
||||
|
||||
_obsRepo.Setup(r => r.FindByPatientId(PatientId))
|
||||
.ReturnsAsync(items);
|
||||
|
||||
var result = await _service.FindLastPumpObservations(PatientId, 1);
|
||||
|
||||
Assert.That(result, Has.Count.EqualTo(1));
|
||||
Assert.That(result[0].Time, Is.EqualTo(items[1].Time));
|
||||
}
|
||||
var items = new List<PumpObservation>
|
||||
{
|
||||
new() { Time = Now.AddMinutes(-10) },
|
||||
new() { Time = Now.AddMinutes(-1) }
|
||||
};
|
||||
|
||||
_obsRepo.Setup(r => r.FindByPatientId(PatientId))
|
||||
.ReturnsAsync(items);
|
||||
|
||||
var result = await _service.FindLastPumpObservations(PatientId, 1);
|
||||
|
||||
Assert.That(result, Has.Count.EqualTo(1));
|
||||
Assert.That(result[0].Time, Is.EqualTo(items[1].Time));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// INSERT MANUAL
|
||||
// --------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Verifies that InsertPumpObservation persists the observation and upserts the corresponding
|
||||
/// pump state when no existing state is found for the device and there are no active subscribers.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task InsertPumpObservation_Inserts_AndBroadcasts()
|
||||
{
|
||||
var obs = new PumpObservation
|
||||
public async Task InsertPumpObservation_Inserts_AndBroadcasts()
|
||||
{
|
||||
DeviceId = "D11",
|
||||
PatientId = PatientId,
|
||||
Time = Now
|
||||
};
|
||||
|
||||
_stateRepo.Setup(r => r.FindByDeviceIdAsync("D11"))
|
||||
.ReturnsAsync((PumpState?)null);
|
||||
|
||||
_subs.Setup(x => x.GetSubscribers()).Returns([]);
|
||||
|
||||
await _service.InsertPumpObservation(obs);
|
||||
|
||||
_obsRepo.Verify(r => r.InsertAsync(It.IsAny<PumpObservation>()), Times.Once);
|
||||
_stateRepo.Verify(r => r.UpsertAsync(It.IsAny<PumpState>()), Times.Once);
|
||||
}
|
||||
var obs = new PumpObservation
|
||||
{
|
||||
DeviceId = "D11",
|
||||
PatientId = PatientId,
|
||||
Time = Now
|
||||
};
|
||||
|
||||
_stateRepo.Setup(r => r.FindByDeviceIdAsync("D11"))
|
||||
.ReturnsAsync((PumpState?)null);
|
||||
|
||||
_subs.Setup(x => x.GetSubscribers()).Returns([]);
|
||||
|
||||
await _service.InsertPumpObservation(obs);
|
||||
|
||||
_obsRepo.Verify(r => r.InsertAsync(It.IsAny<PumpObservation>()), Times.Once);
|
||||
_stateRepo.Verify(r => r.UpsertAsync(It.IsAny<PumpState>()), Times.Once);
|
||||
}
|
||||
}
|
||||
@@ -14,45 +14,48 @@ namespace adas_core.Test.Services;
|
||||
[TestFixture]
|
||||
public class RecordingAlertServiceTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the mocked dependencies and test infrastructure required by the <see cref="RecordingAlertService"/> unit tests, including service and repository mocks, a fake HTTP context with a "TestUser" claim, and the system-under-test instance.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_patientServiceMock = new Mock<IPatientService>();
|
||||
_patientServiceLazy = new Lazy<IPatientService>(() => _patientServiceMock.Object);
|
||||
_configObservationServiceMock = new Mock<IConfigObservationService>();
|
||||
_recordingAlertRepositoryMock = new Mock<IRecordingAlertRepository>();
|
||||
_recordingAlertArchiveRepositoryMock = new Mock<IRecordingAlertArchiveRepository>();
|
||||
_clientMessageServiceMock = new Mock<IClientMessageService>();
|
||||
_subscribersServiceMock = new Mock<ISubscribersService>();
|
||||
var userClaims = new ClaimsPrincipal(new ClaimsIdentity([
|
||||
new Claim(ClaimTypes.Name, "TestUser")
|
||||
], "mock"));
|
||||
|
||||
var httpContextMock = new DefaultHttpContext
|
||||
public void Setup()
|
||||
{
|
||||
User = userClaims
|
||||
};
|
||||
|
||||
_httpContextAccessorMock.Setup(accessor => accessor.HttpContext)
|
||||
.Returns(httpContextMock);
|
||||
|
||||
//optionsApiSettings = Microsoft.Extensions.Options.Options.Create<ApiSettings>(apiSettings);
|
||||
|
||||
_logger = new Mock<ILogger<RecordingAlertService>>();
|
||||
|
||||
_recordingAlertService = new RecordingAlertService(
|
||||
_patientServiceLazy,
|
||||
_configObservationServiceMock.Object,
|
||||
_recordingAlertRepositoryMock.Object,
|
||||
_recordingAlertArchiveRepositoryMock.Object,
|
||||
//optionsApiSettings,
|
||||
_logger.Object,
|
||||
_clientMessageServiceMock.Object,
|
||||
_subscribersServiceMock.Object,
|
||||
_httpContextAccessorMock.Object,
|
||||
_auditServiceMock.Object
|
||||
);
|
||||
}
|
||||
_patientServiceMock = new Mock<IPatientService>();
|
||||
_patientServiceLazy = new Lazy<IPatientService>(() => _patientServiceMock.Object);
|
||||
_configObservationServiceMock = new Mock<IConfigObservationService>();
|
||||
_recordingAlertRepositoryMock = new Mock<IRecordingAlertRepository>();
|
||||
_recordingAlertArchiveRepositoryMock = new Mock<IRecordingAlertArchiveRepository>();
|
||||
_clientMessageServiceMock = new Mock<IClientMessageService>();
|
||||
_subscribersServiceMock = new Mock<ISubscribersService>();
|
||||
var userClaims = new ClaimsPrincipal(new ClaimsIdentity([
|
||||
new Claim(ClaimTypes.Name, "TestUser")
|
||||
], "mock"));
|
||||
|
||||
var httpContextMock = new DefaultHttpContext
|
||||
{
|
||||
User = userClaims
|
||||
};
|
||||
|
||||
_httpContextAccessorMock.Setup(accessor => accessor.HttpContext)
|
||||
.Returns(httpContextMock);
|
||||
|
||||
//optionsApiSettings = Microsoft.Extensions.Options.Options.Create<ApiSettings>(apiSettings);
|
||||
|
||||
_logger = new Mock<ILogger<RecordingAlertService>>();
|
||||
|
||||
_recordingAlertService = new RecordingAlertService(
|
||||
_patientServiceLazy,
|
||||
_configObservationServiceMock.Object,
|
||||
_recordingAlertRepositoryMock.Object,
|
||||
_recordingAlertArchiveRepositoryMock.Object,
|
||||
//optionsApiSettings,
|
||||
_logger.Object,
|
||||
_clientMessageServiceMock.Object,
|
||||
_subscribersServiceMock.Object,
|
||||
_httpContextAccessorMock.Object,
|
||||
_auditServiceMock.Object
|
||||
);
|
||||
}
|
||||
|
||||
private RecordingAlertService _recordingAlertService = null!;
|
||||
private Mock<IPatientService> _patientServiceMock = null!;
|
||||
@@ -78,96 +81,108 @@ public class RecordingAlertServiceTest
|
||||
private static readonly ObjectId PatientId = ObjectId.GenerateNewId();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="RecordingAlertService.SaveRequest"/> does not persist a <see cref="PatientRecordingAlert"/> when the provided <see cref="ApiRequest"/> is neither a recording alert nor an ORU R01 message.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task SaveRequest_Not_RecordingAlert_Not_ORU_R01_Return_not_insert()
|
||||
{
|
||||
var apiRequest = new ApiRequest();
|
||||
|
||||
await _recordingAlertService.SaveRequest(apiRequest);
|
||||
|
||||
_recordingAlertRepositoryMock.Verify(d => d.InsertOneAsync(It.IsAny<PatientRecordingAlert>()), Times.Never);
|
||||
}
|
||||
public async Task SaveRequest_Not_RecordingAlert_Not_ORU_R01_Return_not_insert()
|
||||
{
|
||||
var apiRequest = new ApiRequest();
|
||||
|
||||
await _recordingAlertService.SaveRequest(apiRequest);
|
||||
|
||||
_recordingAlertRepositoryMock.Verify(d => d.InsertOneAsync(It.IsAny<PatientRecordingAlert>()), Times.Never);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="RecordingAlertService.SaveRequest"/> does not insert a <see cref="PatientRecordingAlert"/> when both the patient number and point of care are null in the <see cref="ApiRequest"/>, even when the message type is "ORU_R11".
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task SaveRequest_patientNumber_and_pointOfCare_null_Return_not_insert()
|
||||
{
|
||||
var apiRequest = new ApiRequest
|
||||
public async Task SaveRequest_patientNumber_and_pointOfCare_null_Return_not_insert()
|
||||
{
|
||||
Type = "ORU_R11",
|
||||
MessageTime = Now
|
||||
};
|
||||
|
||||
await _recordingAlertService.SaveRequest(apiRequest);
|
||||
|
||||
_recordingAlertRepositoryMock.Verify(d => d.InsertOneAsync(It.IsAny<PatientRecordingAlert>()), Times.Never);
|
||||
}
|
||||
var apiRequest = new ApiRequest
|
||||
{
|
||||
Type = "ORU_R11",
|
||||
MessageTime = Now
|
||||
};
|
||||
|
||||
await _recordingAlertService.SaveRequest(apiRequest);
|
||||
|
||||
_recordingAlertRepositoryMock.Verify(d => d.InsertOneAsync(It.IsAny<PatientRecordingAlert>()), Times.Never);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the SaveRequest method does not insert a patient recording alert when the specified patient cannot be found.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task SaveRequest_Not_Find_Patient_Return_not_insert()
|
||||
{
|
||||
var person = new Person
|
||||
public async Task SaveRequest_Not_Find_Patient_Return_not_insert()
|
||||
{
|
||||
FirstName = "Miguel",
|
||||
LastName = "Villanueva",
|
||||
Ids = new Dictionary<string, string> { { "MR", "437537" } }
|
||||
};
|
||||
|
||||
var apiRequest = new ApiRequest
|
||||
{
|
||||
Location = new PatientLocation("UCI5C", "Box4"),
|
||||
Patient = person,
|
||||
PatientNumber = "437537",
|
||||
Type = "ORU_R01",
|
||||
PatientId = PatientId.ToString(),
|
||||
MessageTime = Now
|
||||
};
|
||||
|
||||
await _recordingAlertService.SaveRequest(apiRequest);
|
||||
|
||||
_recordingAlertRepositoryMock.Verify(d => d.InsertOneAsync(It.IsAny<PatientRecordingAlert>()), Times.Never);
|
||||
}
|
||||
var person = new Person
|
||||
{
|
||||
FirstName = "Miguel",
|
||||
LastName = "Villanueva",
|
||||
Ids = new Dictionary<string, string> { { "MR", "437537" } }
|
||||
};
|
||||
|
||||
var apiRequest = new ApiRequest
|
||||
{
|
||||
Location = new PatientLocation("UCI5C", "Box4"),
|
||||
Patient = person,
|
||||
PatientNumber = "437537",
|
||||
Type = "ORU_R01",
|
||||
PatientId = PatientId.ToString(),
|
||||
MessageTime = Now
|
||||
};
|
||||
|
||||
await _recordingAlertService.SaveRequest(apiRequest);
|
||||
|
||||
_recordingAlertRepositoryMock.Verify(d => d.InsertOneAsync(It.IsAny<PatientRecordingAlert>()), Times.Never);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that SaveRequest inserts a new <see cref="PatientRecordingAlert"/> into the repository when the configuration observation service returns no retention actions for the given recording alert.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task SaveRequest_Alert_Return_insert()
|
||||
{
|
||||
var person = new Person
|
||||
public async Task SaveRequest_Alert_Return_insert()
|
||||
{
|
||||
FirstName = "Miguel",
|
||||
LastName = "Villanueva",
|
||||
Ids = new Dictionary<string, string> { { "MR", "437537" } }
|
||||
};
|
||||
|
||||
var patient = new Patient
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
UnitString = "UCI5C",
|
||||
Bed = "Box4",
|
||||
PatientNumber = "437537",
|
||||
Person = person
|
||||
};
|
||||
|
||||
var recordingAlert = new PatientRecordingAlert
|
||||
{
|
||||
IsRecording = true
|
||||
};
|
||||
|
||||
var apiRequest = new ApiRequest
|
||||
{
|
||||
Location = new PatientLocation("UCI5C", "Box4"),
|
||||
Patient = person,
|
||||
PatientNumber = "437537",
|
||||
Type = "ORU_R01",
|
||||
PatientId = PatientId.ToString(),
|
||||
MessageTime = Now,
|
||||
RecordingAlert = recordingAlert
|
||||
};
|
||||
|
||||
_patientServiceMock.Setup(p => p.FindPatientByApiRequest(apiRequest)).ReturnsAsync(patient);
|
||||
_configObservationServiceMock.Setup(c => c.RetentionActions(It.IsAny<PatientRecordingAlert>()))
|
||||
.ReturnsAsync((ObservatitonRetentionResult?)null);
|
||||
|
||||
await _recordingAlertService.SaveRequest(apiRequest);
|
||||
|
||||
_recordingAlertRepositoryMock.Verify(d => d.InsertOneAsync(It.IsAny<PatientRecordingAlert>()), Times.Once);
|
||||
}
|
||||
var person = new Person
|
||||
{
|
||||
FirstName = "Miguel",
|
||||
LastName = "Villanueva",
|
||||
Ids = new Dictionary<string, string> { { "MR", "437537" } }
|
||||
};
|
||||
|
||||
var patient = new Patient
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
UnitString = "UCI5C",
|
||||
Bed = "Box4",
|
||||
PatientNumber = "437537",
|
||||
Person = person
|
||||
};
|
||||
|
||||
var recordingAlert = new PatientRecordingAlert
|
||||
{
|
||||
IsRecording = true
|
||||
};
|
||||
|
||||
var apiRequest = new ApiRequest
|
||||
{
|
||||
Location = new PatientLocation("UCI5C", "Box4"),
|
||||
Patient = person,
|
||||
PatientNumber = "437537",
|
||||
Type = "ORU_R01",
|
||||
PatientId = PatientId.ToString(),
|
||||
MessageTime = Now,
|
||||
RecordingAlert = recordingAlert
|
||||
};
|
||||
|
||||
_patientServiceMock.Setup(p => p.FindPatientByApiRequest(apiRequest)).ReturnsAsync(patient);
|
||||
_configObservationServiceMock.Setup(c => c.RetentionActions(It.IsAny<PatientRecordingAlert>()))
|
||||
.ReturnsAsync((ObservatitonRetentionResult?)null);
|
||||
|
||||
await _recordingAlertService.SaveRequest(apiRequest);
|
||||
|
||||
_recordingAlertRepositoryMock.Verify(d => d.InsertOneAsync(It.IsAny<PatientRecordingAlert>()), Times.Once);
|
||||
}
|
||||
}
|
||||
@@ -19,45 +19,50 @@ namespace adas_core.Test.Services;
|
||||
[TestFixture]
|
||||
public class RecordingServiceTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets up the test environment for <see cref="RecordingService"/> by initializing configuration options, creating mock
|
||||
/// dependencies (logger, HTTP client factory, publisher, authentication, client message, subscribers, and patient services),
|
||||
/// and configuring the publisher mock to successfully send both regular messages and errors.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
_optionsRabbitMqSettings = Options.Create(_rabbitMqSettings);
|
||||
_optionsRecordingSettings = Options.Create(_recordingSettings);
|
||||
_publisherServiceMock = new Mock<IPublisherService>();
|
||||
|
||||
_logger = new Mock<ILogger<RecordingService>>();
|
||||
_authServiceMock = new Mock<IAuthService>();
|
||||
|
||||
_httpClientFactoryMock = new Mock<IHttpClientFactory>();
|
||||
_httpMessageHandlerMock = new Mock<HttpMessageHandler>();
|
||||
_clientMessageServiceMock = new Mock<IClientMessageService>();
|
||||
_subscribersServiceMock = new Mock<ISubscribersService>();
|
||||
_patientServiceMock = new Mock<Lazy<IPatientService>>();
|
||||
|
||||
var client = new HttpClient(_httpMessageHandlerMock.Object);
|
||||
|
||||
_httpClientFactoryMock.Setup(c => c.CreateClient(It.IsAny<string>())).Returns(client);
|
||||
|
||||
_recordingService = new RecordingService(
|
||||
_optionsRabbitMqSettings,
|
||||
_optionsRecordingSettings,
|
||||
_logger.Object,
|
||||
_httpClientFactoryMock.Object,
|
||||
_publisherServiceMock.Object,
|
||||
_authServiceMock.Object,
|
||||
_optionsApiSettings,
|
||||
_clientMessageServiceMock.Object,
|
||||
_subscribersServiceMock.Object,
|
||||
_patientServiceMock.Object
|
||||
);
|
||||
|
||||
|
||||
// Set up the mock object to return a specific value when a method is called
|
||||
_publisherServiceMock.Setup(x => x.SendMessage(It.IsAny<object>(), It.IsAny<string>())).ReturnsAsync(true);
|
||||
_publisherServiceMock.Setup(x => x.SendMessageError(It.IsAny<Error>(), It.IsAny<string>())).ReturnsAsync(true);
|
||||
}
|
||||
public void Setup()
|
||||
{
|
||||
_optionsApiSettings = Options.Create(_apiSettings);
|
||||
_optionsRabbitMqSettings = Options.Create(_rabbitMqSettings);
|
||||
_optionsRecordingSettings = Options.Create(_recordingSettings);
|
||||
_publisherServiceMock = new Mock<IPublisherService>();
|
||||
|
||||
_logger = new Mock<ILogger<RecordingService>>();
|
||||
_authServiceMock = new Mock<IAuthService>();
|
||||
|
||||
_httpClientFactoryMock = new Mock<IHttpClientFactory>();
|
||||
_httpMessageHandlerMock = new Mock<HttpMessageHandler>();
|
||||
_clientMessageServiceMock = new Mock<IClientMessageService>();
|
||||
_subscribersServiceMock = new Mock<ISubscribersService>();
|
||||
_patientServiceMock = new Mock<Lazy<IPatientService>>();
|
||||
|
||||
var client = new HttpClient(_httpMessageHandlerMock.Object);
|
||||
|
||||
_httpClientFactoryMock.Setup(c => c.CreateClient(It.IsAny<string>())).Returns(client);
|
||||
|
||||
_recordingService = new RecordingService(
|
||||
_optionsRabbitMqSettings,
|
||||
_optionsRecordingSettings,
|
||||
_logger.Object,
|
||||
_httpClientFactoryMock.Object,
|
||||
_publisherServiceMock.Object,
|
||||
_authServiceMock.Object,
|
||||
_optionsApiSettings,
|
||||
_clientMessageServiceMock.Object,
|
||||
_subscribersServiceMock.Object,
|
||||
_patientServiceMock.Object
|
||||
);
|
||||
|
||||
|
||||
// Set up the mock object to return a specific value when a method is called
|
||||
_publisherServiceMock.Setup(x => x.SendMessage(It.IsAny<object>(), It.IsAny<string>())).ReturnsAsync(true);
|
||||
_publisherServiceMock.Setup(x => x.SendMessageError(It.IsAny<Error>(), It.IsAny<string>())).ReturnsAsync(true);
|
||||
}
|
||||
|
||||
private RecordingService _recordingService = null!;
|
||||
|
||||
@@ -93,95 +98,106 @@ public class RecordingServiceTest
|
||||
private Mock<IClientMessageService> _clientMessageServiceMock = null!;
|
||||
private Mock<ISubscribersService> _subscribersServiceMock = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="RecordingService.GetRecordings"/> returns an empty collection of <see cref="RecordingData"/> when the HTTP response indicates an unauthorized (401) status, ensuring the service correctly handles failed authentication scenarios by yielding no recordings rather than throwing or returning null.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetRecordings_Return_Empty()
|
||||
{
|
||||
var httpResponseMessage = new HttpResponseMessage
|
||||
public async Task GetRecordings_Return_Empty()
|
||||
{
|
||||
StatusCode = HttpStatusCode.Unauthorized,
|
||||
Content = new StringContent("Content text.")
|
||||
};
|
||||
|
||||
var recordingData = new List<RecordingData>();
|
||||
|
||||
_authServiceMock.Setup(s => s.GetToken()).ReturnsAsync("abc");
|
||||
|
||||
_httpMessageHandlerMock.Protected()
|
||||
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
|
||||
ItExpr.IsAny<CancellationToken>())
|
||||
.ReturnsAsync(httpResponseMessage);
|
||||
|
||||
var result = await _recordingService.GetRecordings(4);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
//Assert.AreEqual(result, recordingData);
|
||||
Assert.That(result, Is.EqualTo(recordingData));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetRecordings_Return_RecordingData()
|
||||
{
|
||||
var patient = new Patient
|
||||
{
|
||||
Id = "id",
|
||||
FirstName = "firstName",
|
||||
LastName = "lastName"
|
||||
};
|
||||
|
||||
var recordingData = new List<RecordingData>
|
||||
{
|
||||
new()
|
||||
var httpResponseMessage = new HttpResponseMessage
|
||||
{
|
||||
Patient = patient,
|
||||
RoomId = 4,
|
||||
Status = "INITIALIZED"
|
||||
}
|
||||
};
|
||||
|
||||
var httpResponseMessage = new HttpResponseMessage
|
||||
{
|
||||
StatusCode = HttpStatusCode.OK,
|
||||
Content = new StringContent(JsonConvert.SerializeObject(recordingData), Encoding.UTF8, "application/json")
|
||||
};
|
||||
|
||||
_httpMessageHandlerMock.Protected()
|
||||
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
|
||||
ItExpr.IsAny<CancellationToken>())
|
||||
.ReturnsAsync(httpResponseMessage);
|
||||
|
||||
_authServiceMock.Setup(s => s.GetToken()).ReturnsAsync("abc");
|
||||
|
||||
var result = await _recordingService.GetRecordings(4);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(recordingData[0].Status, Is.EqualTo(result![0].Status));
|
||||
Assert.That(recordingData[0].Patient?.Id, Is.EqualTo(result[0].Patient?.Id));
|
||||
Assert.That(recordingData[0].Patient?.LastName, Is.EqualTo(result[0].Patient?.LastName));
|
||||
Assert.That(recordingData[0].Patient?.FirstName, Is.EqualTo(result[0].Patient?.FirstName));
|
||||
Assert.That(recordingData[0].RoomId, Is.EqualTo(result[0].RoomId));
|
||||
StatusCode = HttpStatusCode.Unauthorized,
|
||||
Content = new StringContent("Content text.")
|
||||
};
|
||||
|
||||
var recordingData = new List<RecordingData>();
|
||||
|
||||
_authServiceMock.Setup(s => s.GetToken()).ReturnsAsync("abc");
|
||||
|
||||
_httpMessageHandlerMock.Protected()
|
||||
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
|
||||
ItExpr.IsAny<CancellationToken>())
|
||||
.ReturnsAsync(httpResponseMessage);
|
||||
|
||||
var result = await _recordingService.GetRecordings(4);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
//Assert.AreEqual(result, recordingData);
|
||||
Assert.That(result, Is.EqualTo(recordingData));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="RecordingService.GetRecordings"/> returns the expected <see cref="RecordingData"/> list
|
||||
/// when the HTTP endpoint responds with a successful payload containing a recording and its associated patient.
|
||||
/// Asserts that the returned items match the source data for status, room identifier, and patient identity fields.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public Task SaveRequest()
|
||||
{
|
||||
ApiRequest apiRequest = new();
|
||||
|
||||
var httpResponseMessage = new HttpResponseMessage
|
||||
public async Task GetRecordings_Return_RecordingData()
|
||||
{
|
||||
StatusCode = HttpStatusCode.OK,
|
||||
Content = new StringContent("Content text.")
|
||||
};
|
||||
var patient = new Patient
|
||||
{
|
||||
Id = "id",
|
||||
FirstName = "firstName",
|
||||
LastName = "lastName"
|
||||
};
|
||||
|
||||
var recordingData = new List<RecordingData>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Patient = patient,
|
||||
RoomId = 4,
|
||||
Status = "INITIALIZED"
|
||||
}
|
||||
};
|
||||
|
||||
var httpResponseMessage = new HttpResponseMessage
|
||||
{
|
||||
StatusCode = HttpStatusCode.OK,
|
||||
Content = new StringContent(JsonConvert.SerializeObject(recordingData), Encoding.UTF8, "application/json")
|
||||
};
|
||||
|
||||
_httpMessageHandlerMock.Protected()
|
||||
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
|
||||
ItExpr.IsAny<CancellationToken>())
|
||||
.ReturnsAsync(httpResponseMessage);
|
||||
|
||||
_authServiceMock.Setup(s => s.GetToken()).ReturnsAsync("abc");
|
||||
|
||||
var result = await _recordingService.GetRecordings(4);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(recordingData[0].Status, Is.EqualTo(result![0].Status));
|
||||
Assert.That(recordingData[0].Patient?.Id, Is.EqualTo(result[0].Patient?.Id));
|
||||
Assert.That(recordingData[0].Patient?.LastName, Is.EqualTo(result[0].Patient?.LastName));
|
||||
Assert.That(recordingData[0].Patient?.FirstName, Is.EqualTo(result[0].Patient?.FirstName));
|
||||
Assert.That(recordingData[0].RoomId, Is.EqualTo(result[0].RoomId));
|
||||
}
|
||||
}
|
||||
|
||||
_httpMessageHandlerMock.Protected()
|
||||
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
|
||||
ItExpr.IsAny<CancellationToken>())
|
||||
.ReturnsAsync(httpResponseMessage);
|
||||
|
||||
Func<Task> act = async () => await _recordingService.SaveRequest(apiRequest);
|
||||
Assert.ThrowsAsync<NotImplementedException>(act);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
/// <summary>
|
||||
/// Tests that calling <c>SaveRequest</c> on the recording service throws a <see cref="NotImplementedException"/> when supplied with an <see cref="ApiRequest"/>, using a mocked HTTP message handler that returns a successful response.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public Task SaveRequest()
|
||||
{
|
||||
ApiRequest apiRequest = new();
|
||||
|
||||
var httpResponseMessage = new HttpResponseMessage
|
||||
{
|
||||
StatusCode = HttpStatusCode.OK,
|
||||
Content = new StringContent("Content text.")
|
||||
};
|
||||
|
||||
_httpMessageHandlerMock.Protected()
|
||||
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
|
||||
ItExpr.IsAny<CancellationToken>())
|
||||
.ReturnsAsync(httpResponseMessage);
|
||||
|
||||
Func<Task> act = async () => await _recordingService.SaveRequest(apiRequest);
|
||||
Assert.ThrowsAsync<NotImplementedException>(act);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -11,165 +11,187 @@ public class RedisLockProviderTest
|
||||
private Mock<IDatabase> _mockDb = null!;
|
||||
private RedisLockProvider _provider = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the test environment by creating a mock <see cref="IDatabase"/> and instantiating a <see cref="RedisLockProvider"/> configured to use the mocked database.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_mockDb = new Mock<IDatabase>();
|
||||
_provider = new RedisLockProvider(() => _mockDb.Object);
|
||||
}
|
||||
public void SetUp()
|
||||
{
|
||||
_mockDb = new Mock<IDatabase>();
|
||||
_provider = new RedisLockProvider(() => _mockDb.Object);
|
||||
}
|
||||
|
||||
#region TC-45
|
||||
/// <summary>
|
||||
/// Verifies that <c>AcquireAsync</c> returns <c>true</c>, stores the lock token under the <c>lock:</c> prefixed key, applies the configured TTL, and uses the <c>When.NotExists</c> flag when Redis accepts the NX SET operation. Also asserts that a subsequent <c>ReleaseAsync</c> invokes the Redis release script.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task AcquireAsync_ReturnsTrue_AndStoresToken_WhenRedisAcceptsNxSet()
|
||||
{
|
||||
_mockDb
|
||||
.Setup(db => db.StringSetAsync(
|
||||
It.IsAny<RedisKey>(),
|
||||
public async Task AcquireAsync_ReturnsTrue_AndStoresToken_WhenRedisAcceptsNxSet()
|
||||
{
|
||||
_mockDb
|
||||
.Setup(db => db.StringSetAsync(
|
||||
It.IsAny<RedisKey>(),
|
||||
It.IsAny<RedisValue>(),
|
||||
It.IsAny<TimeSpan?>(),
|
||||
It.IsAny<When>()))
|
||||
.ReturnsAsync(true);
|
||||
|
||||
_mockDb
|
||||
.Setup(db => db.ScriptEvaluateAsync(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<RedisKey[]?>(),
|
||||
It.IsAny<RedisValue[]?>(),
|
||||
It.IsAny<CommandFlags>()))
|
||||
.Returns(Task.FromResult<RedisResult>(null!));
|
||||
|
||||
var result = await _provider.AcquireAsync("key", TimeSpan.FromSeconds(5));
|
||||
|
||||
Assert.That(result, Is.True);
|
||||
|
||||
_mockDb.Verify(db => db.StringSetAsync(
|
||||
It.Is<RedisKey>(k => k == (RedisKey)"lock:key"),
|
||||
It.IsAny<RedisValue>(),
|
||||
It.IsAny<TimeSpan?>(),
|
||||
It.IsAny<When>()))
|
||||
.ReturnsAsync(true);
|
||||
|
||||
_mockDb
|
||||
.Setup(db => db.ScriptEvaluateAsync(
|
||||
(TimeSpan?)TimeSpan.FromSeconds(5),
|
||||
When.NotExists), Times.Once());
|
||||
|
||||
await _provider.ReleaseAsync("key");
|
||||
|
||||
_mockDb.Verify(db => db.ScriptEvaluateAsync(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<RedisKey[]?>(),
|
||||
It.IsAny<RedisValue[]?>(),
|
||||
It.IsAny<CommandFlags>()))
|
||||
.Returns(Task.FromResult<RedisResult>(null!));
|
||||
|
||||
var result = await _provider.AcquireAsync("key", TimeSpan.FromSeconds(5));
|
||||
|
||||
Assert.That(result, Is.True);
|
||||
|
||||
_mockDb.Verify(db => db.StringSetAsync(
|
||||
It.Is<RedisKey>(k => k == (RedisKey)"lock:key"),
|
||||
It.IsAny<RedisValue>(),
|
||||
(TimeSpan?)TimeSpan.FromSeconds(5),
|
||||
When.NotExists), Times.Once());
|
||||
|
||||
await _provider.ReleaseAsync("key");
|
||||
|
||||
_mockDb.Verify(db => db.ScriptEvaluateAsync(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<RedisKey[]?>(),
|
||||
It.IsAny<RedisValue[]?>(),
|
||||
It.IsAny<CommandFlags>()), Times.Once());
|
||||
}
|
||||
It.IsAny<CommandFlags>()), Times.Once());
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TC-46
|
||||
/// <summary>
|
||||
/// Verifies that <c>AcquireAsync</c> retries the underlying Nx-style <c>StringSetAsync</c> call with delays
|
||||
/// between attempts when the operation initially fails, continuing until it succeeds.
|
||||
/// Asserts the call is retried the expected number of times and that the elapsed time confirms
|
||||
/// delays were actually applied between attempts.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task AcquireAsync_RetriesWithDelays_UntilNxSucceeds()
|
||||
{
|
||||
_mockDb
|
||||
.SetupSequence(db => db.StringSetAsync(
|
||||
public async Task AcquireAsync_RetriesWithDelays_UntilNxSucceeds()
|
||||
{
|
||||
_mockDb
|
||||
.SetupSequence(db => db.StringSetAsync(
|
||||
It.IsAny<RedisKey>(),
|
||||
It.IsAny<RedisValue>(),
|
||||
It.IsAny<TimeSpan?>(),
|
||||
It.IsAny<When>()))
|
||||
.ReturnsAsync(false)
|
||||
.ReturnsAsync(false)
|
||||
.ReturnsAsync(false)
|
||||
.ReturnsAsync(true);
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
var result = await _provider.AcquireAsync("key", TimeSpan.FromSeconds(1));
|
||||
sw.Stop();
|
||||
|
||||
Assert.That(result, Is.True);
|
||||
|
||||
_mockDb.Verify(db => db.StringSetAsync(
|
||||
It.IsAny<RedisKey>(),
|
||||
It.IsAny<RedisValue>(),
|
||||
It.IsAny<TimeSpan?>(),
|
||||
It.IsAny<When>()))
|
||||
.ReturnsAsync(false)
|
||||
.ReturnsAsync(false)
|
||||
.ReturnsAsync(false)
|
||||
.ReturnsAsync(true);
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
var result = await _provider.AcquireAsync("key", TimeSpan.FromSeconds(1));
|
||||
sw.Stop();
|
||||
|
||||
Assert.That(result, Is.True);
|
||||
|
||||
_mockDb.Verify(db => db.StringSetAsync(
|
||||
It.IsAny<RedisKey>(),
|
||||
It.IsAny<RedisValue>(),
|
||||
It.IsAny<TimeSpan?>(),
|
||||
It.IsAny<When>()), Times.Exactly(4));
|
||||
|
||||
Assert.That(sw.ElapsedMilliseconds, Is.GreaterThan(100));
|
||||
}
|
||||
It.IsAny<When>()), Times.Exactly(4));
|
||||
|
||||
Assert.That(sw.ElapsedMilliseconds, Is.GreaterThan(100));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TC-47
|
||||
/// <summary>
|
||||
/// Verifies that AcquireAsync returns <c>false</c> and performs multiple retry attempts when the underlying lock acquisition operation consistently fails within the specified timeout.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task AcquireAsync_ReturnsFalse_AfterTimeoutWithMultipleRetries()
|
||||
{
|
||||
_mockDb
|
||||
.Setup(db => db.StringSetAsync(
|
||||
public async Task AcquireAsync_ReturnsFalse_AfterTimeoutWithMultipleRetries()
|
||||
{
|
||||
_mockDb
|
||||
.Setup(db => db.StringSetAsync(
|
||||
It.IsAny<RedisKey>(),
|
||||
It.IsAny<RedisValue>(),
|
||||
It.IsAny<TimeSpan?>(),
|
||||
It.IsAny<When>()))
|
||||
.ReturnsAsync(false);
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
var result = await _provider.AcquireAsync("key", TimeSpan.FromMilliseconds(200));
|
||||
sw.Stop();
|
||||
|
||||
Assert.That(result, Is.False);
|
||||
Assert.That(sw.ElapsedMilliseconds, Is.GreaterThan(100));
|
||||
|
||||
_mockDb.Verify(db => db.StringSetAsync(
|
||||
It.IsAny<RedisKey>(),
|
||||
It.IsAny<RedisValue>(),
|
||||
It.IsAny<TimeSpan?>(),
|
||||
It.IsAny<When>()))
|
||||
.ReturnsAsync(false);
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
var result = await _provider.AcquireAsync("key", TimeSpan.FromMilliseconds(200));
|
||||
sw.Stop();
|
||||
|
||||
Assert.That(result, Is.False);
|
||||
Assert.That(sw.ElapsedMilliseconds, Is.GreaterThan(100));
|
||||
|
||||
_mockDb.Verify(db => db.StringSetAsync(
|
||||
It.IsAny<RedisKey>(),
|
||||
It.IsAny<RedisValue>(),
|
||||
It.IsAny<TimeSpan?>(),
|
||||
It.IsAny<When>()), Times.AtLeast(2));
|
||||
}
|
||||
It.IsAny<When>()), Times.AtLeast(2));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TC-48
|
||||
/// <summary>
|
||||
/// Verifies that releasing a lock invokes the Lua script evaluation with the correct lock key (prefixed with "lock:") and the token previously captured during lock acquisition.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ReleaseAsync_CallsScriptEvaluateWithCorrectKeyAndToken()
|
||||
{
|
||||
RedisValue capturedToken = default;
|
||||
|
||||
_mockDb
|
||||
.Setup(db => db.StringSetAsync(
|
||||
It.IsAny<RedisKey>(),
|
||||
It.IsAny<RedisValue>(),
|
||||
It.IsAny<TimeSpan?>(),
|
||||
It.IsAny<When>()))
|
||||
.Callback<RedisKey, RedisValue, TimeSpan?, When>(
|
||||
(_, v, _, _) => capturedToken = v)
|
||||
.ReturnsAsync(true);
|
||||
|
||||
_mockDb
|
||||
.Setup(db => db.ScriptEvaluateAsync(
|
||||
public async Task ReleaseAsync_CallsScriptEvaluateWithCorrectKeyAndToken()
|
||||
{
|
||||
RedisValue capturedToken = default;
|
||||
|
||||
_mockDb
|
||||
.Setup(db => db.StringSetAsync(
|
||||
It.IsAny<RedisKey>(),
|
||||
It.IsAny<RedisValue>(),
|
||||
It.IsAny<TimeSpan?>(),
|
||||
It.IsAny<When>()))
|
||||
.Callback<RedisKey, RedisValue, TimeSpan?, When>(
|
||||
(_, v, _, _) => capturedToken = v)
|
||||
.ReturnsAsync(true);
|
||||
|
||||
_mockDb
|
||||
.Setup(db => db.ScriptEvaluateAsync(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<RedisKey[]?>(),
|
||||
It.IsAny<RedisValue[]?>(),
|
||||
It.IsAny<CommandFlags>()))
|
||||
.Returns(Task.FromResult<RedisResult>(null!));
|
||||
|
||||
await _provider.AcquireAsync("key", TimeSpan.FromSeconds(5));
|
||||
await _provider.ReleaseAsync("key");
|
||||
|
||||
_mockDb.Verify(db => db.ScriptEvaluateAsync(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<RedisKey[]?>(),
|
||||
It.IsAny<RedisValue[]?>(),
|
||||
It.IsAny<CommandFlags>()))
|
||||
.Returns(Task.FromResult<RedisResult>(null!));
|
||||
|
||||
await _provider.AcquireAsync("key", TimeSpan.FromSeconds(5));
|
||||
await _provider.ReleaseAsync("key");
|
||||
|
||||
_mockDb.Verify(db => db.ScriptEvaluateAsync(
|
||||
It.IsAny<string>(),
|
||||
It.Is<RedisKey[]?>(keys => keys != null && keys[0] == (RedisKey)"lock:key"),
|
||||
It.Is<RedisValue[]?>(vals => vals != null && vals[0] == capturedToken),
|
||||
It.IsAny<CommandFlags>()), Times.Once());
|
||||
}
|
||||
It.Is<RedisKey[]?>(keys => keys != null && keys[0] == (RedisKey)"lock:key"),
|
||||
It.Is<RedisValue[]?>(vals => vals != null && vals[0] == capturedToken),
|
||||
It.IsAny<CommandFlags>()), Times.Once());
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TC-49
|
||||
/// <summary>
|
||||
/// Verifies that ReleaseAsync is idempotent when invoked without a prior acquire operation,
|
||||
/// ensuring that no script evaluation is performed on the underlying database in this scenario.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ReleaseAsync_IsIdempotent_WhenCalledWithoutPriorAcquire()
|
||||
{
|
||||
_mockDb
|
||||
.Setup(db => db.ScriptEvaluateAsync(
|
||||
public async Task ReleaseAsync_IsIdempotent_WhenCalledWithoutPriorAcquire()
|
||||
{
|
||||
_mockDb
|
||||
.Setup(db => db.ScriptEvaluateAsync(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<RedisKey[]?>(),
|
||||
It.IsAny<RedisValue[]?>(),
|
||||
It.IsAny<CommandFlags>()))
|
||||
.Returns(Task.FromResult<RedisResult>(null!));
|
||||
|
||||
await _provider.ReleaseAsync("key");
|
||||
|
||||
_mockDb.Verify(db => db.ScriptEvaluateAsync(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<RedisKey[]?>(),
|
||||
It.IsAny<RedisValue[]?>(),
|
||||
It.IsAny<CommandFlags>()))
|
||||
.Returns(Task.FromResult<RedisResult>(null!));
|
||||
|
||||
await _provider.ReleaseAsync("key");
|
||||
|
||||
_mockDb.Verify(db => db.ScriptEvaluateAsync(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<RedisKey[]?>(),
|
||||
It.IsAny<RedisValue[]?>(),
|
||||
It.IsAny<CommandFlags>()), Times.Never());
|
||||
}
|
||||
It.IsAny<CommandFlags>()), Times.Never());
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -17,235 +17,291 @@ public class RedisServiceTest
|
||||
private Mock<IDatabase> _mockDb = null!;
|
||||
private LockManagerService _lockMgr = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes test dependencies before each test execution by creating a mock <see cref="IDatabase"/> instance and instantiating the <see cref="LockManagerService"/> with a mocked logger and an in-memory lock provider.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_mockDb = new Mock<IDatabase>();
|
||||
_lockMgr = new LockManagerService(
|
||||
new Mock<ILogger<LockManagerService>>().Object,
|
||||
new InMemoryLockProvider());
|
||||
}
|
||||
public void SetUp()
|
||||
{
|
||||
_mockDb = new Mock<IDatabase>();
|
||||
_lockMgr = new LockManagerService(
|
||||
new Mock<ILogger<LockManagerService>>().Object,
|
||||
new InMemoryLockProvider());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a configured instance of <see cref="RedisService"/> for testing, allowing
|
||||
/// optional customization of cache settings and the simulated availability of the Redis backend.
|
||||
/// </summary>
|
||||
/// <param name="settings">Optional cache settings to apply; when <c>null</c>, a new default <see cref="CacheSettings"/> instance is used.</param>
|
||||
/// <param name="redisAvailable">Flag indicating whether the Redis service should be marked as available; defaults to <c>true</c>.</param>
|
||||
/// <returns>A <see cref="RedisService"/> instance with the database and availability state initialized for testing.</returns>
|
||||
private RedisService CreateSut(CacheSettings? settings = null, bool redisAvailable = true)
|
||||
{
|
||||
var sut = new RedisService(
|
||||
Options.Create(settings ?? new CacheSettings()),
|
||||
new Mock<ILogger<RedisService>>().Object,
|
||||
_lockMgr);
|
||||
|
||||
SetField(sut, "_database", _mockDb.Object);
|
||||
SetField(sut, "_isRedisAvailable", redisAvailable);
|
||||
|
||||
return sut;
|
||||
}
|
||||
{
|
||||
var sut = new RedisService(
|
||||
Options.Create(settings ?? new CacheSettings()),
|
||||
new Mock<ILogger<RedisService>>().Object,
|
||||
_lockMgr);
|
||||
|
||||
SetField(sut, "_database", _mockDb.Object);
|
||||
SetField(sut, "_isRedisAvailable", redisAvailable);
|
||||
|
||||
return sut;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of a non-public instance field on a <see cref="RedisService"/> object using reflection.
|
||||
/// </summary>
|
||||
/// <param name="target">The <see cref="RedisService"/> instance whose field will be set.</param>
|
||||
/// <param name="name">The name of the non-public instance field to assign.</param>
|
||||
/// <param name="value">The value to assign to the field. Can be null.</param>
|
||||
private static void SetField(object target, string name, object? value)
|
||||
=> typeof(RedisService)
|
||||
.GetField(name, BindingFlags.NonPublic | BindingFlags.Instance)!
|
||||
.SetValue(target, value);
|
||||
=> typeof(RedisService)
|
||||
.GetField(name, BindingFlags.NonPublic | BindingFlags.Instance)!
|
||||
.SetValue(target, value);
|
||||
|
||||
/// <summary>
|
||||
/// Configures the mock database to return a successful result (<c>true</c>) for any invocation of <c>StringSetAsync</c>, regardless of the supplied key, value, expiry, overwrite flag, condition, or command flags.
|
||||
/// </summary>
|
||||
private void SetupStringSetAsync()
|
||||
=> _mockDb
|
||||
.Setup(db => db.StringSetAsync(
|
||||
It.IsAny<RedisKey>(), It.IsAny<RedisValue>(), It.IsAny<TimeSpan?>(),
|
||||
It.IsAny<bool>(), It.IsAny<When>(), It.IsAny<CommandFlags>()))
|
||||
.ReturnsAsync(true);
|
||||
=> _mockDb
|
||||
.Setup(db => db.StringSetAsync(
|
||||
It.IsAny<RedisKey>(), It.IsAny<RedisValue>(), It.IsAny<TimeSpan?>(),
|
||||
It.IsAny<bool>(), It.IsAny<When>(), It.IsAny<CommandFlags>()))
|
||||
.ReturnsAsync(true);
|
||||
|
||||
/// <summary>
|
||||
/// Configures the mock Redis database to handle <c>KeyExpire</c> calls by returning <c>true</c> for any combination of key, expiration, condition, and command flag arguments.
|
||||
/// </summary>
|
||||
private void SetupKeyExpire()
|
||||
=> _mockDb
|
||||
.Setup(db => db.KeyExpire(
|
||||
It.IsAny<RedisKey>(), It.IsAny<TimeSpan?>(),
|
||||
It.IsAny<ExpireWhen>(), It.IsAny<CommandFlags>()))
|
||||
.Returns(true);
|
||||
=> _mockDb
|
||||
.Setup(db => db.KeyExpire(
|
||||
It.IsAny<RedisKey>(), It.IsAny<TimeSpan?>(),
|
||||
It.IsAny<ExpireWhen>(), It.IsAny<CommandFlags>()))
|
||||
.Returns(true);
|
||||
|
||||
#region TC-38
|
||||
/// <summary>
|
||||
/// Verifies that <c>GetOrSetObjectAsync</c> invokes the supplied factory when Redis is unavailable, returning the factory's result without attempting any Redis read or write operations.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetOrSetObjectAsync_ExecutesFactory_WhenRedisUnavailable()
|
||||
{
|
||||
var sut = CreateSut(redisAvailable: false);
|
||||
var factoryInvoked = false;
|
||||
|
||||
var result = await sut.GetOrSetObjectAsync<string>(
|
||||
"patients:latestObs:abc",
|
||||
() => { factoryInvoked = true; return Task.FromResult("result"); });
|
||||
|
||||
Assert.That(factoryInvoked, Is.True);
|
||||
Assert.That(result, Is.EqualTo("result"));
|
||||
_mockDb.Verify(db => db.StringGetAsync(It.IsAny<RedisKey>(), It.IsAny<CommandFlags>()), Times.Never);
|
||||
_mockDb.Verify(db => db.StringSetAsync(It.IsAny<RedisKey>(), It.IsAny<RedisValue>(), It.IsAny<TimeSpan?>(), It.IsAny<bool>(), It.IsAny<When>(), It.IsAny<CommandFlags>()), Times.Never);
|
||||
}
|
||||
public async Task GetOrSetObjectAsync_ExecutesFactory_WhenRedisUnavailable()
|
||||
{
|
||||
var sut = CreateSut(redisAvailable: false);
|
||||
var factoryInvoked = false;
|
||||
|
||||
var result = await sut.GetOrSetObjectAsync<string>(
|
||||
"patients:latestObs:abc",
|
||||
() => { factoryInvoked = true; return Task.FromResult("result"); });
|
||||
|
||||
Assert.That(factoryInvoked, Is.True);
|
||||
Assert.That(result, Is.EqualTo("result"));
|
||||
_mockDb.Verify(db => db.StringGetAsync(It.IsAny<RedisKey>(), It.IsAny<CommandFlags>()), Times.Never);
|
||||
_mockDb.Verify(db => db.StringSetAsync(It.IsAny<RedisKey>(), It.IsAny<RedisValue>(), It.IsAny<TimeSpan?>(), It.IsAny<bool>(), It.IsAny<When>(), It.IsAny<CommandFlags>()), Times.Never);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TC-39
|
||||
/// <summary>
|
||||
/// Verifies that <c>GetOrSetObjectAsync</c> returns the cached object deserialized from Redis
|
||||
/// when a value is present in the cache, without invoking the factory delegate and without
|
||||
/// attempting to write back to Redis.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetOrSetObjectAsync_ReturnsCachedObject_WhenRedisHit()
|
||||
{
|
||||
var cached = new TestModel("cached");
|
||||
|
||||
_mockDb.Setup(db => db.StringGetAsync(It.IsAny<RedisKey>(), It.IsAny<CommandFlags>()))
|
||||
.ReturnsAsync((RedisValue)JsonConvert.SerializeObject(cached));
|
||||
SetupKeyExpire();
|
||||
|
||||
var sut = CreateSut();
|
||||
var factoryInvoked = false;
|
||||
|
||||
var result = await sut.GetOrSetObjectAsync<TestModel>(
|
||||
"patients:latestObs:abc",
|
||||
() => { factoryInvoked = true; return Task.FromResult(new TestModel("fresh")); });
|
||||
|
||||
Assert.That(factoryInvoked, Is.False);
|
||||
Assert.That(result?.Name, Is.EqualTo("cached"));
|
||||
_mockDb.Verify(db => db.StringSetAsync(It.IsAny<RedisKey>(), It.IsAny<RedisValue>(), It.IsAny<TimeSpan?>(), It.IsAny<bool>(), It.IsAny<When>(), It.IsAny<CommandFlags>()), Times.Never);
|
||||
}
|
||||
public async Task GetOrSetObjectAsync_ReturnsCachedObject_WhenRedisHit()
|
||||
{
|
||||
var cached = new TestModel("cached");
|
||||
|
||||
_mockDb.Setup(db => db.StringGetAsync(It.IsAny<RedisKey>(), It.IsAny<CommandFlags>()))
|
||||
.ReturnsAsync((RedisValue)JsonConvert.SerializeObject(cached));
|
||||
SetupKeyExpire();
|
||||
|
||||
var sut = CreateSut();
|
||||
var factoryInvoked = false;
|
||||
|
||||
var result = await sut.GetOrSetObjectAsync<TestModel>(
|
||||
"patients:latestObs:abc",
|
||||
() => { factoryInvoked = true; return Task.FromResult(new TestModel("fresh")); });
|
||||
|
||||
Assert.That(factoryInvoked, Is.False);
|
||||
Assert.That(result?.Name, Is.EqualTo("cached"));
|
||||
_mockDb.Verify(db => db.StringSetAsync(It.IsAny<RedisKey>(), It.IsAny<RedisValue>(), It.IsAny<TimeSpan?>(), It.IsAny<bool>(), It.IsAny<When>(), It.IsAny<CommandFlags>()), Times.Never);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TC-40
|
||||
/// <summary>
|
||||
/// Verifies that <c>GetObjectAsync</c> calls the underlying Redis <c>KeyExpire</c> command with the configured TTL
|
||||
/// when the <c>updateExpiration</c> flag is set to <c>true</c>, ensuring cache entries are refreshed upon a successful hit.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetObjectAsync_CallsKeyExpire_WhenUpdateExpirationIsTrue()
|
||||
{
|
||||
var settings = new CacheSettings
|
||||
public async Task GetObjectAsync_CallsKeyExpire_WhenUpdateExpirationIsTrue()
|
||||
{
|
||||
Redis = new RedisSettings { Ttl = new TtlSettings { PatientsSeconds = 300 } }
|
||||
};
|
||||
|
||||
_mockDb.Setup(db => db.StringGetAsync(It.IsAny<RedisKey>(), It.IsAny<CommandFlags>()))
|
||||
.ReturnsAsync((RedisValue)JsonConvert.SerializeObject(new TestModel("hit")));
|
||||
SetupKeyExpire();
|
||||
|
||||
var sut = CreateSut(settings);
|
||||
|
||||
await sut.GetObjectAsync<TestModel>("patients:latestObs:abc", updateExpiration: true);
|
||||
|
||||
_mockDb.Verify(
|
||||
db => db.KeyExpire(
|
||||
It.IsAny<RedisKey>(),
|
||||
It.Is<TimeSpan?>(t => t == TimeSpan.FromSeconds(300)),
|
||||
It.IsAny<ExpireWhen>(),
|
||||
It.IsAny<CommandFlags>()),
|
||||
Times.Once);
|
||||
}
|
||||
var settings = new CacheSettings
|
||||
{
|
||||
Redis = new RedisSettings { Ttl = new TtlSettings { PatientsSeconds = 300 } }
|
||||
};
|
||||
|
||||
_mockDb.Setup(db => db.StringGetAsync(It.IsAny<RedisKey>(), It.IsAny<CommandFlags>()))
|
||||
.ReturnsAsync((RedisValue)JsonConvert.SerializeObject(new TestModel("hit")));
|
||||
SetupKeyExpire();
|
||||
|
||||
var sut = CreateSut(settings);
|
||||
|
||||
await sut.GetObjectAsync<TestModel>("patients:latestObs:abc", updateExpiration: true);
|
||||
|
||||
_mockDb.Verify(
|
||||
db => db.KeyExpire(
|
||||
It.IsAny<RedisKey>(),
|
||||
It.Is<TimeSpan?>(t => t == TimeSpan.FromSeconds(300)),
|
||||
It.IsAny<ExpireWhen>(),
|
||||
It.IsAny<CommandFlags>()),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>GetObjectAsync</c> does not invoke the Redis key expiration command
|
||||
/// when the caller explicitly requests that the existing expiration be left unchanged.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetObjectAsync_DoesNotCallKeyExpire_WhenUpdateExpirationIsFalse()
|
||||
{
|
||||
_mockDb.Setup(db => db.StringGetAsync(It.IsAny<RedisKey>(), It.IsAny<CommandFlags>()))
|
||||
.ReturnsAsync((RedisValue)JsonConvert.SerializeObject(new TestModel("hit")));
|
||||
|
||||
var sut = CreateSut();
|
||||
|
||||
await sut.GetObjectAsync<TestModel>("patients:latestObs:abc", updateExpiration: false);
|
||||
|
||||
_mockDb.Verify(
|
||||
db => db.KeyExpire(It.IsAny<RedisKey>(), It.IsAny<TimeSpan?>(), It.IsAny<ExpireWhen>(), It.IsAny<CommandFlags>()),
|
||||
Times.Never);
|
||||
}
|
||||
public async Task GetObjectAsync_DoesNotCallKeyExpire_WhenUpdateExpirationIsFalse()
|
||||
{
|
||||
_mockDb.Setup(db => db.StringGetAsync(It.IsAny<RedisKey>(), It.IsAny<CommandFlags>()))
|
||||
.ReturnsAsync((RedisValue)JsonConvert.SerializeObject(new TestModel("hit")));
|
||||
|
||||
var sut = CreateSut();
|
||||
|
||||
await sut.GetObjectAsync<TestModel>("patients:latestObs:abc", updateExpiration: false);
|
||||
|
||||
_mockDb.Verify(
|
||||
db => db.KeyExpire(It.IsAny<RedisKey>(), It.IsAny<TimeSpan?>(), It.IsAny<ExpireWhen>(), It.IsAny<CommandFlags>()),
|
||||
Times.Never);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TC-41
|
||||
/// <summary>
|
||||
/// Verifies that <c>GetOrSetObjectAsync</c> invokes the supplied factory and persists the resulting object
|
||||
/// to Redis with the configured TTL when the cache lookup returns a miss (i.e., the stored value is null).
|
||||
/// Ensures the factory delegate is executed, the deserialized value matches the factory output, and the
|
||||
/// object is written to cache with the expected expiration.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetOrSetObjectAsync_InvokesFactoryAndPersists_WhenCacheMiss()
|
||||
{
|
||||
var settings = new CacheSettings
|
||||
public async Task GetOrSetObjectAsync_InvokesFactoryAndPersists_WhenCacheMiss()
|
||||
{
|
||||
Redis = new RedisSettings { Ttl = new TtlSettings { PatientsSeconds = 300, PatientObservationsSeconds = 300} }
|
||||
};
|
||||
|
||||
_mockDb.Setup(db => db.StringGetAsync(It.IsAny<RedisKey>(), It.IsAny<CommandFlags>()))
|
||||
.ReturnsAsync(RedisValue.Null);
|
||||
SetupStringSetAsync();
|
||||
|
||||
var sut = CreateSut(settings);
|
||||
var expected = new TestModel("fresh");
|
||||
var factoryInvoked = false;
|
||||
|
||||
var result = await sut.GetOrSetObjectAsync<TestModel>(
|
||||
"patients:latestObs:abc",
|
||||
() => { factoryInvoked = true; return Task.FromResult(expected); });
|
||||
|
||||
var expectedJson = JsonConvert.SerializeObject(expected);
|
||||
|
||||
Assert.That(factoryInvoked, Is.True);
|
||||
Assert.That(result?.Name, Is.EqualTo("fresh"));
|
||||
_mockDb.Verify(
|
||||
db => db.StringSetAsync(
|
||||
It.IsAny<RedisKey>(),
|
||||
It.IsAny<RedisValue>(),
|
||||
It.Is<TimeSpan?>(t => t == TimeSpan.FromSeconds(300)),
|
||||
It.IsAny<bool>(),
|
||||
It.IsAny<When>(),
|
||||
It.IsAny<CommandFlags>()),
|
||||
Times.Once);
|
||||
It.Is<RedisValue>(v => v.Equals(expectedJson));
|
||||
}
|
||||
var settings = new CacheSettings
|
||||
{
|
||||
Redis = new RedisSettings { Ttl = new TtlSettings { PatientsSeconds = 300, PatientObservationsSeconds = 300} }
|
||||
};
|
||||
|
||||
_mockDb.Setup(db => db.StringGetAsync(It.IsAny<RedisKey>(), It.IsAny<CommandFlags>()))
|
||||
.ReturnsAsync(RedisValue.Null);
|
||||
SetupStringSetAsync();
|
||||
|
||||
var sut = CreateSut(settings);
|
||||
var expected = new TestModel("fresh");
|
||||
var factoryInvoked = false;
|
||||
|
||||
var result = await sut.GetOrSetObjectAsync<TestModel>(
|
||||
"patients:latestObs:abc",
|
||||
() => { factoryInvoked = true; return Task.FromResult(expected); });
|
||||
|
||||
var expectedJson = JsonConvert.SerializeObject(expected);
|
||||
|
||||
Assert.That(factoryInvoked, Is.True);
|
||||
Assert.That(result?.Name, Is.EqualTo("fresh"));
|
||||
_mockDb.Verify(
|
||||
db => db.StringSetAsync(
|
||||
It.IsAny<RedisKey>(),
|
||||
It.IsAny<RedisValue>(),
|
||||
It.Is<TimeSpan?>(t => t == TimeSpan.FromSeconds(300)),
|
||||
It.IsAny<bool>(),
|
||||
It.IsAny<When>(),
|
||||
It.IsAny<CommandFlags>()),
|
||||
Times.Once);
|
||||
It.Is<RedisValue>(v => v.Equals(expectedJson));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TC-42
|
||||
/// <summary>
|
||||
/// Verifies that when the cache lookup returns no value and the factory delegate produces <c>null</c>,
|
||||
/// the method returns <c>null</c> and does not persist any value to the underlying cache store.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetOrSetObjectAsync_DoesNotPersist_WhenFactoryReturnsNull()
|
||||
{
|
||||
_mockDb.Setup(db => db.StringGetAsync(It.IsAny<RedisKey>(), It.IsAny<CommandFlags>()))
|
||||
.ReturnsAsync(RedisValue.Null);
|
||||
|
||||
var sut = CreateSut();
|
||||
|
||||
var result = await sut.GetOrSetObjectAsync<TestModel?>(
|
||||
"patients:latestObs:abc",
|
||||
() => Task.FromResult<TestModel?>(null));
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
_mockDb.Verify(
|
||||
db => db.StringSetAsync(It.IsAny<RedisKey>(), It.IsAny<RedisValue>(), It.IsAny<TimeSpan?>(), It.IsAny<bool>(), It.IsAny<When>(), It.IsAny<CommandFlags>()),
|
||||
Times.Never);
|
||||
}
|
||||
public async Task GetOrSetObjectAsync_DoesNotPersist_WhenFactoryReturnsNull()
|
||||
{
|
||||
_mockDb.Setup(db => db.StringGetAsync(It.IsAny<RedisKey>(), It.IsAny<CommandFlags>()))
|
||||
.ReturnsAsync(RedisValue.Null);
|
||||
|
||||
var sut = CreateSut();
|
||||
|
||||
var result = await sut.GetOrSetObjectAsync<TestModel?>(
|
||||
"patients:latestObs:abc",
|
||||
() => Task.FromResult<TestModel?>(null));
|
||||
|
||||
Assert.That(result, Is.Null);
|
||||
_mockDb.Verify(
|
||||
db => db.StringSetAsync(It.IsAny<RedisKey>(), It.IsAny<RedisValue>(), It.IsAny<TimeSpan?>(), It.IsAny<bool>(), It.IsAny<When>(), It.IsAny<CommandFlags>()),
|
||||
Times.Never);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TC-43
|
||||
/// <summary>
|
||||
/// Verifies that <c>GetObjectAsync</c> successfully retrieves and deserializes the stored object while skipping the
|
||||
/// key-expiration refresh when <c>updateExpiration</c> is set to <c>false</c>, ensuring <c>KeyExpire</c> is never invoked.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetObjectAsync_ReturnsObject_AndSkipsKeyExpire_WhenUpdateExpirationFalse()
|
||||
{
|
||||
var expected = new TestModel("data");
|
||||
|
||||
_mockDb.Setup(db => db.StringGetAsync(It.IsAny<RedisKey>(), It.IsAny<CommandFlags>()))
|
||||
.ReturnsAsync((RedisValue)JsonConvert.SerializeObject(expected));
|
||||
|
||||
var sut = CreateSut();
|
||||
|
||||
var result = await sut.GetObjectAsync<TestModel>("patients:latestObs:abc", updateExpiration: false);
|
||||
|
||||
Assert.That(result?.Name, Is.EqualTo("data"));
|
||||
_mockDb.Verify(
|
||||
db => db.KeyExpire(It.IsAny<RedisKey>(), It.IsAny<TimeSpan?>(), It.IsAny<ExpireWhen>(), It.IsAny<CommandFlags>()),
|
||||
Times.Never);
|
||||
}
|
||||
public async Task GetObjectAsync_ReturnsObject_AndSkipsKeyExpire_WhenUpdateExpirationFalse()
|
||||
{
|
||||
var expected = new TestModel("data");
|
||||
|
||||
_mockDb.Setup(db => db.StringGetAsync(It.IsAny<RedisKey>(), It.IsAny<CommandFlags>()))
|
||||
.ReturnsAsync((RedisValue)JsonConvert.SerializeObject(expected));
|
||||
|
||||
var sut = CreateSut();
|
||||
|
||||
var result = await sut.GetObjectAsync<TestModel>("patients:latestObs:abc", updateExpiration: false);
|
||||
|
||||
Assert.That(result?.Name, Is.EqualTo("data"));
|
||||
_mockDb.Verify(
|
||||
db => db.KeyExpire(It.IsAny<RedisKey>(), It.IsAny<TimeSpan?>(), It.IsAny<ExpireWhen>(), It.IsAny<CommandFlags>()),
|
||||
Times.Never);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TC-44
|
||||
/// <summary>
|
||||
/// Verifies that <c>SetObjectAsync</c> serializes the supplied object to JSON and persists it in Redis
|
||||
/// with the entity-specific TTL (600 seconds) configured for the "Patients" entity in <see cref="CacheSettings"/>.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task SetObjectAsync_SerializesToJson_AndPersistsWithEntityTtl()
|
||||
{
|
||||
var settings = new CacheSettings
|
||||
public async Task SetObjectAsync_SerializesToJson_AndPersistsWithEntityTtl()
|
||||
{
|
||||
Redis = new RedisSettings { Ttl = new TtlSettings { PatientsSeconds = 600 } }
|
||||
};
|
||||
|
||||
SetupStringSetAsync();
|
||||
|
||||
var sut = CreateSut(settings);
|
||||
var obj = new TestModel("save-me");
|
||||
var expectedJson = JsonConvert.SerializeObject(obj);
|
||||
|
||||
await sut.SetObjectAsync("patients:latestObs:abc", obj, null, true);
|
||||
_mockDb.Verify(
|
||||
db => db.StringSetAsync(
|
||||
It.IsAny<RedisKey>(),
|
||||
It.IsAny<RedisValue>(),
|
||||
It.Is<TimeSpan?>(t => t == TimeSpan.FromSeconds(600)),
|
||||
It.IsAny<bool>(),
|
||||
It.IsAny<When>(),
|
||||
It.IsAny<CommandFlags>()),
|
||||
Times.Once);
|
||||
It.Is<RedisValue>(v => v.Equals(expectedJson));
|
||||
|
||||
}
|
||||
var settings = new CacheSettings
|
||||
{
|
||||
Redis = new RedisSettings { Ttl = new TtlSettings { PatientsSeconds = 600 } }
|
||||
};
|
||||
|
||||
SetupStringSetAsync();
|
||||
|
||||
var sut = CreateSut(settings);
|
||||
var obj = new TestModel("save-me");
|
||||
var expectedJson = JsonConvert.SerializeObject(obj);
|
||||
|
||||
await sut.SetObjectAsync("patients:latestObs:abc", obj, null, true);
|
||||
_mockDb.Verify(
|
||||
db => db.StringSetAsync(
|
||||
It.IsAny<RedisKey>(),
|
||||
It.IsAny<RedisValue>(),
|
||||
It.Is<TimeSpan?>(t => t == TimeSpan.FromSeconds(600)),
|
||||
It.IsAny<bool>(),
|
||||
It.IsAny<When>(),
|
||||
It.IsAny<CommandFlags>()),
|
||||
Times.Once);
|
||||
It.Is<RedisValue>(v => v.Equals(expectedJson));
|
||||
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -16,26 +16,29 @@ namespace adas_core.Test.Services;
|
||||
[TestFixture]
|
||||
public class RelayServiceTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets up the test environment by initializing mocks and dependencies required for unit testing the <see cref="RelayService"/>, including logger, HTTP client factory, HTTP message handler, relay settings, point-of-care service, and relay repository.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_logger = new Mock<ILogger<RelayService>>();
|
||||
_httpClientFactoryMock = new Mock<IHttpClientFactory>();
|
||||
_httpMessageHandlerMock = new Mock<HttpMessageHandler>();
|
||||
_relaySettings.RecordingOrApiUrl = "http://localhost:8080";
|
||||
_relaySettings.Cache = true;
|
||||
_optionsRelaySettings = Options.Create(_relaySettings);
|
||||
_pocServiceMock = new Mock<IPointOfCareService>();
|
||||
_relayRepositoryMock = new Mock<IRelayRepository>();
|
||||
|
||||
_relayService = new RelayService(
|
||||
//optionsApiSettings,
|
||||
_logger.Object,
|
||||
_httpClientFactoryMock.Object,
|
||||
_optionsRelaySettings,
|
||||
_pocServiceMock.Object,
|
||||
_relayRepositoryMock.Object);
|
||||
}
|
||||
public void Setup()
|
||||
{
|
||||
_logger = new Mock<ILogger<RelayService>>();
|
||||
_httpClientFactoryMock = new Mock<IHttpClientFactory>();
|
||||
_httpMessageHandlerMock = new Mock<HttpMessageHandler>();
|
||||
_relaySettings.RecordingOrApiUrl = "http://localhost:8080";
|
||||
_relaySettings.Cache = true;
|
||||
_optionsRelaySettings = Options.Create(_relaySettings);
|
||||
_pocServiceMock = new Mock<IPointOfCareService>();
|
||||
_relayRepositoryMock = new Mock<IRelayRepository>();
|
||||
|
||||
_relayService = new RelayService(
|
||||
//optionsApiSettings,
|
||||
_logger.Object,
|
||||
_httpClientFactoryMock.Object,
|
||||
_optionsRelaySettings,
|
||||
_pocServiceMock.Object,
|
||||
_relayRepositoryMock.Object);
|
||||
}
|
||||
|
||||
private RelayService _relayService = null!;
|
||||
private Mock<IHttpClientFactory> _httpClientFactoryMock = null!;
|
||||
@@ -52,117 +55,126 @@ public class RelayServiceTest
|
||||
|
||||
private Mock<ILogger<RelayService>> _logger = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the relay service successfully powers off a relay by issuing an HTTP request through the configured HTTP client factory.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task PowerOffAsync()
|
||||
{
|
||||
var relay = new Relay
|
||||
public async Task PowerOffAsync()
|
||||
{
|
||||
Driver = "KMTronicV2",
|
||||
Ip = "10.133.10.169",
|
||||
Port = 80,
|
||||
RelayNumber = 1,
|
||||
RelayName = "Relay1",
|
||||
Total = 8,
|
||||
Username = "adas",
|
||||
Password = "!HULPM22"
|
||||
};
|
||||
|
||||
|
||||
var httpResponseMessage = new HttpResponseMessage
|
||||
{
|
||||
StatusCode = HttpStatusCode.OK,
|
||||
Content = new StringContent("Test content")
|
||||
};
|
||||
|
||||
_httpMessageHandlerMock.Protected()
|
||||
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
|
||||
ItExpr.IsAny<CancellationToken>())
|
||||
.ReturnsAsync(httpResponseMessage);
|
||||
|
||||
|
||||
var client = new HttpClient(_httpMessageHandlerMock.Object);
|
||||
|
||||
_httpClientFactoryMock.Setup(c => c.CreateClient(It.IsAny<string>())).Returns(client);
|
||||
|
||||
await _relayService.PowerOff(relay);
|
||||
}
|
||||
var relay = new Relay
|
||||
{
|
||||
Driver = "KMTronicV2",
|
||||
Ip = "10.133.10.169",
|
||||
Port = 80,
|
||||
RelayNumber = 1,
|
||||
RelayName = "Relay1",
|
||||
Total = 8,
|
||||
Username = "adas",
|
||||
Password = "!HULPM22"
|
||||
};
|
||||
|
||||
|
||||
var httpResponseMessage = new HttpResponseMessage
|
||||
{
|
||||
StatusCode = HttpStatusCode.OK,
|
||||
Content = new StringContent("Test content")
|
||||
};
|
||||
|
||||
_httpMessageHandlerMock.Protected()
|
||||
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
|
||||
ItExpr.IsAny<CancellationToken>())
|
||||
.ReturnsAsync(httpResponseMessage);
|
||||
|
||||
|
||||
var client = new HttpClient(_httpMessageHandlerMock.Object);
|
||||
|
||||
_httpClientFactoryMock.Setup(c => c.CreateClient(It.IsAny<string>())).Returns(client);
|
||||
|
||||
await _relayService.PowerOff(relay);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="RelayService.PowerOn"/> correctly sends a power-on request to the configured relay device using the HTTP client.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task PowerOnAsync()
|
||||
{
|
||||
var relay = new Relay
|
||||
public async Task PowerOnAsync()
|
||||
{
|
||||
Driver = "KMTronicV2",
|
||||
Ip = "10.133.10.169",
|
||||
Port = 80,
|
||||
RelayNumber = 1,
|
||||
RelayName = "Relay1",
|
||||
Total = 8,
|
||||
Username = "adas",
|
||||
Password = "!HULPM22"
|
||||
};
|
||||
|
||||
|
||||
var httpResponseMessage = new HttpResponseMessage
|
||||
{
|
||||
StatusCode = HttpStatusCode.OK,
|
||||
Content = new StringContent("Test content")
|
||||
};
|
||||
|
||||
_httpMessageHandlerMock.Protected()
|
||||
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
|
||||
ItExpr.IsAny<CancellationToken>())
|
||||
.ReturnsAsync(httpResponseMessage);
|
||||
|
||||
|
||||
var client = new HttpClient(_httpMessageHandlerMock.Object);
|
||||
|
||||
_httpClientFactoryMock.Setup(c => c.CreateClient(It.IsAny<string>())).Returns(client);
|
||||
|
||||
await _relayService.PowerOn(relay);
|
||||
}
|
||||
var relay = new Relay
|
||||
{
|
||||
Driver = "KMTronicV2",
|
||||
Ip = "10.133.10.169",
|
||||
Port = 80,
|
||||
RelayNumber = 1,
|
||||
RelayName = "Relay1",
|
||||
Total = 8,
|
||||
Username = "adas",
|
||||
Password = "!HULPM22"
|
||||
};
|
||||
|
||||
|
||||
var httpResponseMessage = new HttpResponseMessage
|
||||
{
|
||||
StatusCode = HttpStatusCode.OK,
|
||||
Content = new StringContent("Test content")
|
||||
};
|
||||
|
||||
_httpMessageHandlerMock.Protected()
|
||||
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
|
||||
ItExpr.IsAny<CancellationToken>())
|
||||
.ReturnsAsync(httpResponseMessage);
|
||||
|
||||
|
||||
var client = new HttpClient(_httpMessageHandlerMock.Object);
|
||||
|
||||
_httpClientFactoryMock.Setup(c => c.CreateClient(It.IsAny<string>())).Returns(client);
|
||||
|
||||
await _relayService.PowerOn(relay);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>CheckRelayStatus</c> returns <see cref="RelayEnum.Status.On"/> when the mocked HTTP response indicates the relay is on.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task CheckRelayStatus_Return_On()
|
||||
{
|
||||
var relay = new Relay
|
||||
public async Task CheckRelayStatus_Return_On()
|
||||
{
|
||||
Driver = "KMTronicV2",
|
||||
Ip = "10.133.10.169",
|
||||
Port = 80,
|
||||
RelayNumber = 1,
|
||||
RelayName = "Relay1",
|
||||
Total = 8,
|
||||
Username = "adas",
|
||||
Password = "!HULPM22"
|
||||
};
|
||||
|
||||
var httpResponseMessage = new HttpResponseMessage
|
||||
{
|
||||
StatusCode = HttpStatusCode.OK,
|
||||
Content = new StringContent("\"On")
|
||||
};
|
||||
|
||||
_httpMessageHandlerMock.Protected()
|
||||
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
|
||||
ItExpr.IsAny<CancellationToken>())
|
||||
.ReturnsAsync(httpResponseMessage);
|
||||
|
||||
//httpMessageHandlerMock.Protected()
|
||||
// .Setup<Task<string>>("ReadAsStringAsync", ItExpr.IsAny<string>(), ItExpr.IsAny<CancellationToken>())
|
||||
// .ReturnsAsync("\\On");
|
||||
|
||||
|
||||
var client = new HttpClient(_httpMessageHandlerMock.Object);
|
||||
|
||||
_httpClientFactoryMock.Setup(c => c.CreateClient(It.IsAny<string>())).Returns(client);
|
||||
|
||||
await _relayService.PowerOn(relay);
|
||||
var result = await _relayService.CheckRelayStatus(relay);
|
||||
|
||||
//Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.EqualTo(RelayEnum.Status.On));
|
||||
}
|
||||
var relay = new Relay
|
||||
{
|
||||
Driver = "KMTronicV2",
|
||||
Ip = "10.133.10.169",
|
||||
Port = 80,
|
||||
RelayNumber = 1,
|
||||
RelayName = "Relay1",
|
||||
Total = 8,
|
||||
Username = "adas",
|
||||
Password = "!HULPM22"
|
||||
};
|
||||
|
||||
var httpResponseMessage = new HttpResponseMessage
|
||||
{
|
||||
StatusCode = HttpStatusCode.OK,
|
||||
Content = new StringContent("\"On")
|
||||
};
|
||||
|
||||
_httpMessageHandlerMock.Protected()
|
||||
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
|
||||
ItExpr.IsAny<CancellationToken>())
|
||||
.ReturnsAsync(httpResponseMessage);
|
||||
|
||||
//httpMessageHandlerMock.Protected()
|
||||
// .Setup<Task<string>>("ReadAsStringAsync", ItExpr.IsAny<string>(), ItExpr.IsAny<CancellationToken>())
|
||||
// .ReturnsAsync("\\On");
|
||||
|
||||
|
||||
var client = new HttpClient(_httpMessageHandlerMock.Object);
|
||||
|
||||
_httpClientFactoryMock.Setup(c => c.CreateClient(It.IsAny<string>())).Returns(client);
|
||||
|
||||
await _relayService.PowerOn(relay);
|
||||
var result = await _relayService.CheckRelayStatus(relay);
|
||||
|
||||
//Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.EqualTo(RelayEnum.Status.On));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task CheckRelayStatus_Return_Off()
|
||||
@@ -201,41 +213,46 @@ public class RelayServiceTest
|
||||
Assert.That(result, Is.EqualTo(RelayEnum.Status.Off));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>CheckRelayStatus</c> returns <see cref="RelayEnum.Status.Unknown"/> when the relay
|
||||
/// driver response does not match a recognized on/off state (e.g., the raw payload "\\Off" is not
|
||||
/// mapped to a known status).
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task CheckRelayStatus_Return_Unknown()
|
||||
{
|
||||
var relay = new Relay
|
||||
public async Task CheckRelayStatus_Return_Unknown()
|
||||
{
|
||||
Driver = "KMTronicV2",
|
||||
Ip = "10.133.10.169",
|
||||
Port = 80,
|
||||
RelayNumber = 1,
|
||||
RelayName = "Relay1",
|
||||
Total = 8,
|
||||
Username = "adas",
|
||||
Password = "!HULPM22"
|
||||
};
|
||||
|
||||
|
||||
var httpResponseMessage = new HttpResponseMessage
|
||||
{
|
||||
StatusCode = HttpStatusCode.OK,
|
||||
Content = new StringContent("\\Off")
|
||||
};
|
||||
|
||||
_httpMessageHandlerMock.Protected()
|
||||
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
|
||||
ItExpr.IsAny<CancellationToken>())
|
||||
.ReturnsAsync(httpResponseMessage);
|
||||
|
||||
|
||||
var client = new HttpClient(_httpMessageHandlerMock.Object);
|
||||
|
||||
_httpClientFactoryMock.Setup(c => c.CreateClient(It.IsAny<string>())).Returns(client);
|
||||
|
||||
var result = await _relayService.CheckRelayStatus(relay);
|
||||
|
||||
//Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.EqualTo(RelayEnum.Status.Unknown));
|
||||
}
|
||||
var relay = new Relay
|
||||
{
|
||||
Driver = "KMTronicV2",
|
||||
Ip = "10.133.10.169",
|
||||
Port = 80,
|
||||
RelayNumber = 1,
|
||||
RelayName = "Relay1",
|
||||
Total = 8,
|
||||
Username = "adas",
|
||||
Password = "!HULPM22"
|
||||
};
|
||||
|
||||
|
||||
var httpResponseMessage = new HttpResponseMessage
|
||||
{
|
||||
StatusCode = HttpStatusCode.OK,
|
||||
Content = new StringContent("\\Off")
|
||||
};
|
||||
|
||||
_httpMessageHandlerMock.Protected()
|
||||
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
|
||||
ItExpr.IsAny<CancellationToken>())
|
||||
.ReturnsAsync(httpResponseMessage);
|
||||
|
||||
|
||||
var client = new HttpClient(_httpMessageHandlerMock.Object);
|
||||
|
||||
_httpClientFactoryMock.Setup(c => c.CreateClient(It.IsAny<string>())).Returns(client);
|
||||
|
||||
var result = await _relayService.CheckRelayStatus(relay);
|
||||
|
||||
//Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.EqualTo(RelayEnum.Status.Unknown));
|
||||
}
|
||||
}
|
||||
@@ -323,268 +323,294 @@ public class SchedulerServiceTest
|
||||
private static readonly ObjectId PatientId = ObjectId.GenerateNewId();
|
||||
private static readonly ObjectId PatientId2 = ObjectId.GenerateNewId();
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the <see cref="CheckInactivePatientsJob"/> is executed when its Quartz.NET trigger fires,
|
||||
/// ensuring the scheduled job invokes the patient discharge process for inactive patients at the configured interval.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CheckInactivePatientsJob_ShouldExecuteOnTrigger()
|
||||
{
|
||||
var checkInactivePatientSchedulerIntervalHours = 12;
|
||||
|
||||
// Arrange
|
||||
var checkInactivePatientsJob = JobBuilder.Create<CheckInactivePatientsJob>()
|
||||
.UsingJobData(_jobDataMap)
|
||||
.Build();
|
||||
|
||||
// Crear un disparador personalizado que incremente el contador
|
||||
var checkInactivePatientsTrigger = TriggerBuilder.Create()
|
||||
.StartNow()
|
||||
.WithSimpleSchedule(x => x
|
||||
.WithIntervalInHours(checkInactivePatientSchedulerIntervalHours)
|
||||
.RepeatForever())
|
||||
.Build();
|
||||
|
||||
|
||||
_patientServiceMock?.Setup(p => p.DischargeInactivePatients(_sinceDate, _sinceDischargeTimeToArchive));
|
||||
|
||||
// Asociar el trabajo y el desencadenador en el motor de Quartz.NET
|
||||
_scheduler?.ScheduleJob(checkInactivePatientsJob, checkInactivePatientsTrigger).Wait();
|
||||
|
||||
// Act
|
||||
// Esperar un tiempo suficiente para que el trabajo se ejecute varias veces
|
||||
Thread.Sleep(TimeSpan.FromSeconds(1));
|
||||
|
||||
|
||||
_patientServiceMock?.Verify(p => p.DischargeInactivePatients(It.IsAny<DateTime>(), It.IsAny<int>()),
|
||||
Times.AtLeastOnce());
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void CheckActiveTreatmentsJob_ShouldExecuteOnTrigger()
|
||||
{
|
||||
var patient = new Patient
|
||||
public void CheckInactivePatientsJob_ShouldExecuteOnTrigger()
|
||||
{
|
||||
PatientId = PatientId.ToString(),
|
||||
UnitString = "NEONATAL",
|
||||
Bed = "CINA02",
|
||||
PatientNumber = "123456",
|
||||
Person = new Person
|
||||
{
|
||||
FirstName = "Jose",
|
||||
LastName = "Luis",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
};
|
||||
var checkInactivePatientSchedulerIntervalHours = 12;
|
||||
|
||||
// Arrange
|
||||
var checkInactivePatientsJob = JobBuilder.Create<CheckInactivePatientsJob>()
|
||||
.UsingJobData(_jobDataMap)
|
||||
.Build();
|
||||
|
||||
// Crear un disparador personalizado que incremente el contador
|
||||
var checkInactivePatientsTrigger = TriggerBuilder.Create()
|
||||
.StartNow()
|
||||
.WithSimpleSchedule(x => x
|
||||
.WithIntervalInHours(checkInactivePatientSchedulerIntervalHours)
|
||||
.RepeatForever())
|
||||
.Build();
|
||||
|
||||
|
||||
_patientServiceMock?.Setup(p => p.DischargeInactivePatients(_sinceDate, _sinceDischargeTimeToArchive));
|
||||
|
||||
// Asociar el trabajo y el desencadenador en el motor de Quartz.NET
|
||||
_scheduler?.ScheduleJob(checkInactivePatientsJob, checkInactivePatientsTrigger).Wait();
|
||||
|
||||
// Act
|
||||
// Esperar un tiempo suficiente para que el trabajo se ejecute varias veces
|
||||
Thread.Sleep(TimeSpan.FromSeconds(1));
|
||||
|
||||
|
||||
_patientServiceMock?.Verify(p => p.DischargeInactivePatients(It.IsAny<DateTime>(), It.IsAny<int>()),
|
||||
Times.AtLeastOnce());
|
||||
}
|
||||
|
||||
const int checkActiveTreatmentsSchedulerIntervalMinutes = 10;
|
||||
|
||||
var treatmentsJob = JobBuilder.Create<CheckActiveTreatmentsJob>()
|
||||
.Build();
|
||||
|
||||
// Trigger the job to run now, and then repeat every 10 seconds
|
||||
var treatmentsTrigger = TriggerBuilder.Create()
|
||||
.StartNow()
|
||||
.WithSimpleSchedule(x => x
|
||||
.WithIntervalInMinutes(checkActiveTreatmentsSchedulerIntervalMinutes)
|
||||
.RepeatForever())
|
||||
.Build();
|
||||
|
||||
_patientServiceMock?.Setup(p => p.FindAll(It.IsAny<bool>())).ReturnsAsync([patient]);
|
||||
|
||||
// Create a mock of the singleton class subscribers
|
||||
var mockSingleton = new Mock<ICalculatedObservationsService>();
|
||||
|
||||
// Set up the mock object to return a specific value when a method is called
|
||||
var patientTreatmentList = new List<PatientTreatment?>
|
||||
/// <summary>
|
||||
/// Verifies that the <see cref="CheckActiveTreatmentsJob"/> is executed by the Quartz scheduler
|
||||
/// when triggered, and that the medicine service is invoked exactly once to retrieve medicines
|
||||
/// for the active treatments of the mocked patients.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CheckActiveTreatmentsJob_ShouldExecuteOnTrigger()
|
||||
{
|
||||
new()
|
||||
var patient = new Patient
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = PatientId,
|
||||
OrderControl = OrderControlType.Nw,
|
||||
PlacerOrder = new Entity { EntityIdentifier = "3690", NamespaceId = "CareVue" },
|
||||
FillerOrder = new Entity { EntityIdentifier = "3690", NamespaceId = "CareVue" },
|
||||
OrderStatus = "A",
|
||||
OrderTime = Now,
|
||||
Notes = [],
|
||||
Routes = []
|
||||
}
|
||||
};
|
||||
|
||||
mockSingleton.Setup(x => x.GetActiveTreatmentsByPatient(PatientId)).ReturnsAsync(patientTreatmentList);
|
||||
|
||||
|
||||
_medicineServiceMock?.Setup(m => m.GetMedicinesOfTreatments(It.IsAny<List<PatientTreatment>>()))
|
||||
.ReturnsAsync(new List<Medicine>());
|
||||
|
||||
// Asociar el trabajo y el desencadenador en el motor de Quartz.NET
|
||||
_scheduler?.ScheduleJob(treatmentsJob, treatmentsTrigger).Wait();
|
||||
|
||||
// Act
|
||||
// Esperar un tiempo suficiente para que el trabajo se ejecute varias veces
|
||||
Thread.Sleep(TimeSpan.FromSeconds(10));
|
||||
|
||||
_medicineServiceMock?.Verify(x => x.GetMedicinesOfTreatments(It.IsAny<IEnumerable<PatientTreatment>>()),
|
||||
Times.Once());
|
||||
}
|
||||
PatientId = PatientId.ToString(),
|
||||
UnitString = "NEONATAL",
|
||||
Bed = "CINA02",
|
||||
PatientNumber = "123456",
|
||||
Person = new Person
|
||||
{
|
||||
FirstName = "Jose",
|
||||
LastName = "Luis",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
};
|
||||
|
||||
const int checkActiveTreatmentsSchedulerIntervalMinutes = 10;
|
||||
|
||||
var treatmentsJob = JobBuilder.Create<CheckActiveTreatmentsJob>()
|
||||
.Build();
|
||||
|
||||
// Trigger the job to run now, and then repeat every 10 seconds
|
||||
var treatmentsTrigger = TriggerBuilder.Create()
|
||||
.StartNow()
|
||||
.WithSimpleSchedule(x => x
|
||||
.WithIntervalInMinutes(checkActiveTreatmentsSchedulerIntervalMinutes)
|
||||
.RepeatForever())
|
||||
.Build();
|
||||
|
||||
_patientServiceMock?.Setup(p => p.FindAll(It.IsAny<bool>())).ReturnsAsync([patient]);
|
||||
|
||||
// Create a mock of the singleton class subscribers
|
||||
var mockSingleton = new Mock<ICalculatedObservationsService>();
|
||||
|
||||
// Set up the mock object to return a specific value when a method is called
|
||||
var patientTreatmentList = new List<PatientTreatment?>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientId = PatientId,
|
||||
OrderControl = OrderControlType.Nw,
|
||||
PlacerOrder = new Entity { EntityIdentifier = "3690", NamespaceId = "CareVue" },
|
||||
FillerOrder = new Entity { EntityIdentifier = "3690", NamespaceId = "CareVue" },
|
||||
OrderStatus = "A",
|
||||
OrderTime = Now,
|
||||
Notes = [],
|
||||
Routes = []
|
||||
}
|
||||
};
|
||||
|
||||
mockSingleton.Setup(x => x.GetActiveTreatmentsByPatient(PatientId)).ReturnsAsync(patientTreatmentList);
|
||||
|
||||
|
||||
_medicineServiceMock?.Setup(m => m.GetMedicinesOfTreatments(It.IsAny<List<PatientTreatment>>()))
|
||||
.ReturnsAsync(new List<Medicine>());
|
||||
|
||||
// Asociar el trabajo y el desencadenador en el motor de Quartz.NET
|
||||
_scheduler?.ScheduleJob(treatmentsJob, treatmentsTrigger).Wait();
|
||||
|
||||
// Act
|
||||
// Esperar un tiempo suficiente para que el trabajo se ejecute varias veces
|
||||
Thread.Sleep(TimeSpan.FromSeconds(10));
|
||||
|
||||
_medicineServiceMock?.Verify(x => x.GetMedicinesOfTreatments(It.IsAny<IEnumerable<PatientTreatment>>()),
|
||||
Times.Once());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the <see cref="CheckExpiredObservationsJob"/> is executed at least once by the Quartz.NET scheduler when triggered with a recurring schedule.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CheckExpiredObservationsJob_ShouldExecuteOnTrigger()
|
||||
{
|
||||
var checkExpiredObservationsIntervalMinutes = 3;
|
||||
|
||||
// Arrange
|
||||
var checkExpiredObservationsJob = JobBuilder.Create<CheckExpiredObservationsJob>()
|
||||
.UsingJobData(_jobDataMap)
|
||||
.Build();
|
||||
|
||||
// Crear un disparador personalizado que incremente el contador
|
||||
var checkExpiredObservationsTrigger = TriggerBuilder.Create()
|
||||
.StartNow()
|
||||
.WithSimpleSchedule(x => x
|
||||
.WithIntervalInHours(checkExpiredObservationsIntervalMinutes)
|
||||
.RepeatForever())
|
||||
.Build();
|
||||
|
||||
// Asociar el trabajo y el desencadenador en el motor de Quartz.NET
|
||||
_scheduler?.ScheduleJob(checkExpiredObservationsJob, checkExpiredObservationsTrigger).Wait();
|
||||
|
||||
// Act
|
||||
// Esperar un tiempo suficiente para que el trabajo se ejecute varias veces
|
||||
Thread.Sleep(TimeSpan.FromSeconds(1));
|
||||
|
||||
|
||||
_observationServiceMock?.Verify(p => p.ExpireObservationsAndRecalculateAsync(), Times.AtLeastOnce());
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void CheckExpiredAlertsJob_ShouldExecuteOnTrigger()
|
||||
{
|
||||
var checkExpiredAlertsIntervalMinutes = 3;
|
||||
|
||||
// Arrange
|
||||
var checkExpiredAlertsJob = JobBuilder.Create<CheckExpiredAlertsJob>()
|
||||
.UsingJobData(_jobDataMap)
|
||||
.Build();
|
||||
|
||||
// Crear un disparador personalizado que incremente el contador
|
||||
var checkExpiredAlertsTrigger = TriggerBuilder.Create()
|
||||
.StartNow()
|
||||
.WithSimpleSchedule(x => x
|
||||
.WithIntervalInHours(checkExpiredAlertsIntervalMinutes)
|
||||
.RepeatForever())
|
||||
.Build();
|
||||
|
||||
// Asociar el trabajo y el desencadenador en el motor de Quartz.NET
|
||||
_scheduler?.ScheduleJob(checkExpiredAlertsJob, checkExpiredAlertsTrigger).Wait();
|
||||
|
||||
// Act
|
||||
// Esperar un tiempo suficiente para que el trabajo se ejecute varias veces
|
||||
Thread.Sleep(TimeSpan.FromSeconds(1));
|
||||
|
||||
|
||||
_observationServiceMock?.Verify(p => p.ExpireAlertsAndPowerOffAsync(), Times.AtLeastOnce());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetProvidersObservationsJob_ShouldExecuteOnTrigger_Result_GetType_null()
|
||||
{
|
||||
var getProviderObservationsIntervalMinutes = 5;
|
||||
|
||||
var patient = new Patient
|
||||
public void CheckExpiredObservationsJob_ShouldExecuteOnTrigger()
|
||||
{
|
||||
PatientId = PatientId.ToString(),
|
||||
UnitString = "NEONATAL",
|
||||
Bed = "CINA02",
|
||||
PatientNumber = "123456",
|
||||
Person = new Person
|
||||
var checkExpiredObservationsIntervalMinutes = 3;
|
||||
|
||||
// Arrange
|
||||
var checkExpiredObservationsJob = JobBuilder.Create<CheckExpiredObservationsJob>()
|
||||
.UsingJobData(_jobDataMap)
|
||||
.Build();
|
||||
|
||||
// Crear un disparador personalizado que incremente el contador
|
||||
var checkExpiredObservationsTrigger = TriggerBuilder.Create()
|
||||
.StartNow()
|
||||
.WithSimpleSchedule(x => x
|
||||
.WithIntervalInHours(checkExpiredObservationsIntervalMinutes)
|
||||
.RepeatForever())
|
||||
.Build();
|
||||
|
||||
// Asociar el trabajo y el desencadenador en el motor de Quartz.NET
|
||||
_scheduler?.ScheduleJob(checkExpiredObservationsJob, checkExpiredObservationsTrigger).Wait();
|
||||
|
||||
// Act
|
||||
// Esperar un tiempo suficiente para que el trabajo se ejecute varias veces
|
||||
Thread.Sleep(TimeSpan.FromSeconds(1));
|
||||
|
||||
|
||||
_observationServiceMock?.Verify(p => p.ExpireObservationsAndRecalculateAsync(), Times.AtLeastOnce());
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the <see cref="CheckExpiredAlertsJob"/> is executed when triggered by the Quartz.NET scheduler, ensuring that the <c>ExpireAlertsAndPowerOffAsync</c> method on the observation service is invoked at least once.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CheckExpiredAlertsJob_ShouldExecuteOnTrigger()
|
||||
{
|
||||
var checkExpiredAlertsIntervalMinutes = 3;
|
||||
|
||||
// Arrange
|
||||
var checkExpiredAlertsJob = JobBuilder.Create<CheckExpiredAlertsJob>()
|
||||
.UsingJobData(_jobDataMap)
|
||||
.Build();
|
||||
|
||||
// Crear un disparador personalizado que incremente el contador
|
||||
var checkExpiredAlertsTrigger = TriggerBuilder.Create()
|
||||
.StartNow()
|
||||
.WithSimpleSchedule(x => x
|
||||
.WithIntervalInHours(checkExpiredAlertsIntervalMinutes)
|
||||
.RepeatForever())
|
||||
.Build();
|
||||
|
||||
// Asociar el trabajo y el desencadenador en el motor de Quartz.NET
|
||||
_scheduler?.ScheduleJob(checkExpiredAlertsJob, checkExpiredAlertsTrigger).Wait();
|
||||
|
||||
// Act
|
||||
// Esperar un tiempo suficiente para que el trabajo se ejecute varias veces
|
||||
Thread.Sleep(TimeSpan.FromSeconds(1));
|
||||
|
||||
|
||||
_observationServiceMock?.Verify(p => p.ExpireAlertsAndPowerOffAsync(), Times.AtLeastOnce());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the <see cref="GetProvidersObservationsJob"/> Quartz.NET job, when triggered, never invokes
|
||||
/// <c>InsertObservation</c> with a <see cref="PatientObservation"/> whose <c>Name</c> is not "NEWS", ensuring
|
||||
/// that only NEWS observations are considered for persistence during scheduled execution.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void GetProvidersObservationsJob_ShouldExecuteOnTrigger_Result_GetType_null()
|
||||
{
|
||||
var getProviderObservationsIntervalMinutes = 5;
|
||||
|
||||
var patient = new Patient
|
||||
{
|
||||
FirstName = "Jose",
|
||||
LastName = "Luis",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
};
|
||||
|
||||
// Arrange
|
||||
var getProvidersObservationsJob = JobBuilder.Create<GetProvidersObservationsJob>()
|
||||
.UsingJobData(_jobDataMap)
|
||||
.Build();
|
||||
|
||||
// Crear un disparador personalizado que incremente el contador
|
||||
var getProvidersObservationsTrigger = TriggerBuilder.Create()
|
||||
.StartNow()
|
||||
.WithSimpleSchedule(x => x
|
||||
.WithIntervalInHours(getProviderObservationsIntervalMinutes)
|
||||
.RepeatForever())
|
||||
.Build();
|
||||
|
||||
_patientServiceMock?.Setup(p => p.FindAll(It.IsAny<bool>())).ReturnsAsync([patient]);
|
||||
|
||||
// Asociar el trabajo y el desencadenador en el motor de Quartz.NET
|
||||
_scheduler?.ScheduleJob(getProvidersObservationsJob, getProvidersObservationsTrigger).Wait();
|
||||
|
||||
// Act
|
||||
// Esperar un tiempo suficiente para que el trabajo se ejecute varias veces
|
||||
Thread.Sleep(TimeSpan.FromSeconds(1));
|
||||
|
||||
//observationServiceMock.Verify(p => p.InsertObservation(It.IsAny<PatientObservation>(),true,true), Times.AtLeastOnce());
|
||||
_observationServiceMock?.Verify(p => p.InsertObservation(
|
||||
It.Is<PatientObservation>(obs => obs.Name != "NEWS"), true, true), Times.Never());
|
||||
}
|
||||
PatientId = PatientId.ToString(),
|
||||
UnitString = "NEONATAL",
|
||||
Bed = "CINA02",
|
||||
PatientNumber = "123456",
|
||||
Person = new Person
|
||||
{
|
||||
FirstName = "Jose",
|
||||
LastName = "Luis",
|
||||
BirthDate = new DateTime(),
|
||||
Gender = PatientEnum.Gender.Male
|
||||
}
|
||||
};
|
||||
|
||||
// Arrange
|
||||
var getProvidersObservationsJob = JobBuilder.Create<GetProvidersObservationsJob>()
|
||||
.UsingJobData(_jobDataMap)
|
||||
.Build();
|
||||
|
||||
// Crear un disparador personalizado que incremente el contador
|
||||
var getProvidersObservationsTrigger = TriggerBuilder.Create()
|
||||
.StartNow()
|
||||
.WithSimpleSchedule(x => x
|
||||
.WithIntervalInHours(getProviderObservationsIntervalMinutes)
|
||||
.RepeatForever())
|
||||
.Build();
|
||||
|
||||
_patientServiceMock?.Setup(p => p.FindAll(It.IsAny<bool>())).ReturnsAsync([patient]);
|
||||
|
||||
// Asociar el trabajo y el desencadenador en el motor de Quartz.NET
|
||||
_scheduler?.ScheduleJob(getProvidersObservationsJob, getProvidersObservationsTrigger).Wait();
|
||||
|
||||
// Act
|
||||
// Esperar un tiempo suficiente para que el trabajo se ejecute varias veces
|
||||
Thread.Sleep(TimeSpan.FromSeconds(1));
|
||||
|
||||
//observationServiceMock.Verify(p => p.InsertObservation(It.IsAny<PatientObservation>(),true,true), Times.AtLeastOnce());
|
||||
_observationServiceMock?.Verify(p => p.InsertObservation(
|
||||
It.Is<PatientObservation>(obs => obs.Name != "NEWS"), true, true), Times.Never());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the <see cref="CalculateNewsJob"/> is executed when triggered by the Quartz.NET scheduler, confirming that the associated <c>InsertObservation</c> call on the observation service is invoked at least once within the allowed execution window.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CheckCalculateNewsJob_ShouldExecuteOnTrigger()
|
||||
{
|
||||
var checkExpiredAlertsIntervalMinutes = 3;
|
||||
|
||||
// Arrange
|
||||
var calculateNewsJob = JobBuilder.Create<CalculateNewsJob>()
|
||||
.UsingJobData(_jobDataMap)
|
||||
.Build();
|
||||
|
||||
// Crear un disparador personalizado que incremente el contador
|
||||
var checkExpiredAlertsTrigger = TriggerBuilder.Create()
|
||||
.StartNow()
|
||||
.WithSimpleSchedule(x => x
|
||||
.WithIntervalInHours(checkExpiredAlertsIntervalMinutes)
|
||||
.RepeatForever())
|
||||
.Build();
|
||||
|
||||
// Asociar el trabajo y el desencadenador en el motor de Quartz.NET
|
||||
_scheduler?.ScheduleJob(calculateNewsJob, checkExpiredAlertsTrigger).Wait();
|
||||
|
||||
// Act
|
||||
// Esperar un tiempo suficiente para que el trabajo se ejecute varias veces
|
||||
Thread.Sleep(TimeSpan.FromSeconds(6));
|
||||
|
||||
|
||||
_observationServiceMock?.Verify(p => p.InsertObservation(It.IsAny<PatientObservation>(), true, true),
|
||||
Times.AtLeastOnce());
|
||||
}
|
||||
public void CheckCalculateNewsJob_ShouldExecuteOnTrigger()
|
||||
{
|
||||
var checkExpiredAlertsIntervalMinutes = 3;
|
||||
|
||||
// Arrange
|
||||
var calculateNewsJob = JobBuilder.Create<CalculateNewsJob>()
|
||||
.UsingJobData(_jobDataMap)
|
||||
.Build();
|
||||
|
||||
// Crear un disparador personalizado que incremente el contador
|
||||
var checkExpiredAlertsTrigger = TriggerBuilder.Create()
|
||||
.StartNow()
|
||||
.WithSimpleSchedule(x => x
|
||||
.WithIntervalInHours(checkExpiredAlertsIntervalMinutes)
|
||||
.RepeatForever())
|
||||
.Build();
|
||||
|
||||
// Asociar el trabajo y el desencadenador en el motor de Quartz.NET
|
||||
_scheduler?.ScheduleJob(calculateNewsJob, checkExpiredAlertsTrigger).Wait();
|
||||
|
||||
// Act
|
||||
// Esperar un tiempo suficiente para que el trabajo se ejecute varias veces
|
||||
Thread.Sleep(TimeSpan.FromSeconds(6));
|
||||
|
||||
|
||||
_observationServiceMock?.Verify(p => p.InsertObservation(It.IsAny<PatientObservation>(), true, true),
|
||||
Times.AtLeastOnce());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="CalculateNewsJob.Execute"/> correctly inserts NEWS observations with the expected calculated values (1 and 4) for multiple patients in a single execution.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task CalculateNewsJob_Insert_ObsFull_MultiplePatient_With_Correct_Value()
|
||||
{
|
||||
var job = new CalculateNewsJob();
|
||||
|
||||
// Act
|
||||
await job.Execute(Mock.Of<IJobExecutionContext>());
|
||||
|
||||
// Assert
|
||||
_observationServiceMock?.Verify(
|
||||
service => service.InsertObservation(
|
||||
It.Is<PatientObservation>(obs =>
|
||||
obs.Name == "NEWS" && (int)obs.Value == 1 && obs.PatientId == PatientId),
|
||||
true, true),
|
||||
Times.Once);
|
||||
|
||||
_observationServiceMock?.Verify(
|
||||
service => service.InsertObservation(
|
||||
It.Is<PatientObservation>(obs =>
|
||||
obs.Name == "NEWS" && (int)obs.Value == 4 && obs.PatientId == PatientId2),
|
||||
true, true),
|
||||
Times.Once);
|
||||
}
|
||||
public async Task CalculateNewsJob_Insert_ObsFull_MultiplePatient_With_Correct_Value()
|
||||
{
|
||||
var job = new CalculateNewsJob();
|
||||
|
||||
// Act
|
||||
await job.Execute(Mock.Of<IJobExecutionContext>());
|
||||
|
||||
// Assert
|
||||
_observationServiceMock?.Verify(
|
||||
service => service.InsertObservation(
|
||||
It.Is<PatientObservation>(obs =>
|
||||
obs.Name == "NEWS" && (int)obs.Value == 1 && obs.PatientId == PatientId),
|
||||
true, true),
|
||||
Times.Once);
|
||||
|
||||
_observationServiceMock?.Verify(
|
||||
service => service.InsertObservation(
|
||||
It.Is<PatientObservation>(obs =>
|
||||
obs.Name == "NEWS" && (int)obs.Value == 4 && obs.PatientId == PatientId2),
|
||||
true, true),
|
||||
Times.Once);
|
||||
}
|
||||
//Se deshabilita el mensaje de warning porque lo detecta como no usado y sugiere suprimirlo siendo necesario
|
||||
}
|
||||
@@ -10,26 +10,31 @@ namespace adas_core.Test.Services;
|
||||
[TestFixture]
|
||||
public class SendAlertServiceTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes test dependencies for <see cref="SendAlertService"/> unit tests, including
|
||||
/// RabbitMQ options, a mocked logger, an instance of the service under test, and the set
|
||||
/// of Windows platform identifiers used to validate platform-specific behavior.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_optionsRabbitMqSettings = Options.Create(_rabbitMqSettings);
|
||||
|
||||
_logger = new Mock<ILogger<SendAlertService>>();
|
||||
|
||||
_sendAlertService = new SendAlertService(
|
||||
_optionsRabbitMqSettings,
|
||||
_logger.Object
|
||||
);
|
||||
|
||||
_windowsPlatforms =
|
||||
[
|
||||
PlatformID.Win32NT,
|
||||
PlatformID.Win32S,
|
||||
PlatformID.Win32Windows,
|
||||
PlatformID.WinCE
|
||||
];
|
||||
}
|
||||
public void Setup()
|
||||
{
|
||||
_optionsRabbitMqSettings = Options.Create(_rabbitMqSettings);
|
||||
|
||||
_logger = new Mock<ILogger<SendAlertService>>();
|
||||
|
||||
_sendAlertService = new SendAlertService(
|
||||
_optionsRabbitMqSettings,
|
||||
_logger.Object
|
||||
);
|
||||
|
||||
_windowsPlatforms =
|
||||
[
|
||||
PlatformID.Win32NT,
|
||||
PlatformID.Win32S,
|
||||
PlatformID.Win32Windows,
|
||||
PlatformID.WinCE
|
||||
];
|
||||
}
|
||||
|
||||
private SendAlertService _sendAlertService = null!;
|
||||
|
||||
@@ -40,76 +45,89 @@ public class SendAlertServiceTest
|
||||
|
||||
private PlatformID[] _windowsPlatforms = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="_sendAlertService"/>.<c>GetConsumedCpu</c> returns a valid performance CPU
|
||||
/// reading (non-null with a positive <c>ValueTotal</c>) when executed on a Windows platform. When the
|
||||
/// host operating system is not Windows, the test is skipped with an ignore notice.
|
||||
/// </summary>
|
||||
[Ignore("Integration test to pull request")]
|
||||
[Test]
|
||||
public void GetConsumedCpu_Return_PerformanceCpu_data()
|
||||
{
|
||||
if (_windowsPlatforms.Contains(Environment.OSVersion.Platform))
|
||||
[Test]
|
||||
public void GetConsumedCpu_Return_PerformanceCpu_data()
|
||||
{
|
||||
var result = _sendAlertService.GetConsumedCpu();
|
||||
//result = await sendAlertService.GetConsumedCpu();
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.ValueTotal, Is.GreaterThan(0));
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Ignore("This test can only be run on Windows.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Ignore("Integration test to pull request")]
|
||||
[Test]
|
||||
public void GetConsumedRAM_Return_PerformanceRAM_data()
|
||||
{
|
||||
if (_windowsPlatforms.Contains(Environment.OSVersion.Platform))
|
||||
{
|
||||
var result = _sendAlertService.GetConsumedRam();
|
||||
//result = await sendAlertService.GetConsumedRAM();
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
using (Assert.EnterMultipleScope())
|
||||
if (_windowsPlatforms.Contains(Environment.OSVersion.Platform))
|
||||
{
|
||||
Assert.That(result.PercentageConsumed, Is.GreaterThan(0));
|
||||
Assert.That(result.ValueConsumed, Is.GreaterThan(0));
|
||||
var result = _sendAlertService.GetConsumedCpu();
|
||||
//result = await sendAlertService.GetConsumedCpu();
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.ValueTotal, Is.GreaterThan(0));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Ignore("This test can only be run on Windows.");
|
||||
}
|
||||
}
|
||||
|
||||
[Ignore("Integration test to pull request")]
|
||||
[Test]
|
||||
public void GetConsumedStorage_Return_PerformanceStorage_data()
|
||||
{
|
||||
if (_windowsPlatforms.Contains(Environment.OSVersion.Platform))
|
||||
{
|
||||
List<Performance> performanceList = [];
|
||||
|
||||
foreach (var drive in DriveInfo.GetDrives())
|
||||
if (drive.IsReady)
|
||||
{
|
||||
var performance = _sendAlertService.GetConsumedStorage(drive);
|
||||
|
||||
performanceList.Add(performance);
|
||||
}
|
||||
|
||||
Assert.That(performanceList, Is.Not.Null);
|
||||
using (Assert.EnterMultipleScope())
|
||||
else
|
||||
{
|
||||
Assert.That(performanceList, Is.Not.Empty);
|
||||
Assert.That(performanceList[0].PercentageConsumed, Is.GreaterThan(0));
|
||||
Assert.That(performanceList[0].ValueConsumed, Is.GreaterThan(0));
|
||||
Assert.That(performanceList[0].ValueTotal, Is.GreaterThan(0));
|
||||
Assert.Ignore("This test can only be run on Windows.");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>GetConsumedRam</c> returns a non-null performance RAM data object with positive values
|
||||
/// for <c>PercentageConsumed</c>, <c>ValueConsumed</c>, and <c>ValueTotal</c>. The test only executes on
|
||||
/// Windows platforms and is ignored on other operating systems.
|
||||
/// </summary>
|
||||
[Ignore("Integration test to pull request")]
|
||||
[Test]
|
||||
public void GetConsumedRAM_Return_PerformanceRAM_data()
|
||||
{
|
||||
Assert.Ignore("This test can only be run on Windows.");
|
||||
if (_windowsPlatforms.Contains(Environment.OSVersion.Platform))
|
||||
{
|
||||
var result = _sendAlertService.GetConsumedRam();
|
||||
//result = await sendAlertService.GetConsumedRAM();
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(result.PercentageConsumed, Is.GreaterThan(0));
|
||||
Assert.That(result.ValueConsumed, Is.GreaterThan(0));
|
||||
Assert.That(result.ValueTotal, Is.GreaterThan(0));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Ignore("This test can only be run on Windows.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Integration test that verifies the GetConsumedStorage method returns valid Performance data with positive percentage and value metrics for all ready drives on Windows platforms. The test is ignored when executed on a non-Windows platform.
|
||||
/// </summary>
|
||||
[Ignore("Integration test to pull request")]
|
||||
[Test]
|
||||
public void GetConsumedStorage_Return_PerformanceStorage_data()
|
||||
{
|
||||
if (_windowsPlatforms.Contains(Environment.OSVersion.Platform))
|
||||
{
|
||||
List<Performance> performanceList = [];
|
||||
|
||||
foreach (var drive in DriveInfo.GetDrives())
|
||||
if (drive.IsReady)
|
||||
{
|
||||
var performance = _sendAlertService.GetConsumedStorage(drive);
|
||||
|
||||
performanceList.Add(performance);
|
||||
}
|
||||
|
||||
Assert.That(performanceList, Is.Not.Null);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(performanceList, Is.Not.Empty);
|
||||
Assert.That(performanceList[0].PercentageConsumed, Is.GreaterThan(0));
|
||||
Assert.That(performanceList[0].ValueConsumed, Is.GreaterThan(0));
|
||||
Assert.That(performanceList[0].ValueTotal, Is.GreaterThan(0));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Ignore("This test can only be run on Windows.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,18 +10,21 @@ namespace adas_core.Test.Services;
|
||||
[TestFixture]
|
||||
public class ServiceConfigServiceTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the test environment by creating mock instances of the service configuration repository and logger, and instantiating the <see cref="ServiceConfigService"/> under test.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_serviceConfigRepositoryMock = new Mock<IServiceConfigRepository>();
|
||||
|
||||
_logger = new Mock<ILogger<ServiceConfigService>>();
|
||||
|
||||
_serviceConfigService = new ServiceConfigService(
|
||||
_serviceConfigRepositoryMock.Object,
|
||||
_logger.Object
|
||||
);
|
||||
}
|
||||
public void Setup()
|
||||
{
|
||||
_serviceConfigRepositoryMock = new Mock<IServiceConfigRepository>();
|
||||
|
||||
_logger = new Mock<ILogger<ServiceConfigService>>();
|
||||
|
||||
_serviceConfigService = new ServiceConfigService(
|
||||
_serviceConfigRepositoryMock.Object,
|
||||
_logger.Object
|
||||
);
|
||||
}
|
||||
|
||||
private ServiceConfigService _serviceConfigService;
|
||||
|
||||
@@ -30,34 +33,41 @@ public class ServiceConfigServiceTest
|
||||
|
||||
private static ObjectId _id = ObjectId.GenerateNewId();
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the <see cref="ServiceConfig"/> service returns a <see cref="ServiceConfig"/> instance
|
||||
/// when retrieving an existing configuration by its string identifier.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Get_Find_Id_Return_ServiceConfig()
|
||||
{
|
||||
var serviceConfig = new ServiceConfig
|
||||
public async Task Get_Find_Id_Return_ServiceConfig()
|
||||
{
|
||||
StrId = _id.ToString()
|
||||
};
|
||||
|
||||
_serviceConfigRepositoryMock.Setup(s => s.FindById(_id.ToString())).ReturnsAsync(serviceConfig);
|
||||
|
||||
var result = await _serviceConfigService.Get(serviceConfig.StrId);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
var serviceConfig = new ServiceConfig
|
||||
{
|
||||
StrId = _id.ToString()
|
||||
};
|
||||
|
||||
_serviceConfigRepositoryMock.Setup(s => s.FindById(_id.ToString())).ReturnsAsync(serviceConfig);
|
||||
|
||||
var result = await _serviceConfigService.Get(serviceConfig.StrId);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the Get method returns a <see cref="ServiceConfig"/> when the specified id is not found by the repository's <c>FindById</c>, falling back to a lookup with any <see cref="ObjectId"/>.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Get_Not_Find_Id_Return_ServiceConfig()
|
||||
{
|
||||
var serviceConfig = new ServiceConfig
|
||||
public async Task Get_Not_Find_Id_Return_ServiceConfig()
|
||||
{
|
||||
StrId = _id.ToString()
|
||||
};
|
||||
|
||||
_serviceConfigRepositoryMock.Setup(s => s.FindById(_id)).ReturnsAsync((ServiceConfig?)null);
|
||||
_serviceConfigRepositoryMock.Setup(s => s.FindById(It.IsAny<ObjectId>())).ReturnsAsync(serviceConfig);
|
||||
|
||||
var result = await _serviceConfigService.Get(_id.ToString());
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
var serviceConfig = new ServiceConfig
|
||||
{
|
||||
StrId = _id.ToString()
|
||||
};
|
||||
|
||||
_serviceConfigRepositoryMock.Setup(s => s.FindById(_id)).ReturnsAsync((ServiceConfig?)null);
|
||||
_serviceConfigRepositoryMock.Setup(s => s.FindById(It.IsAny<ObjectId>())).ReturnsAsync(serviceConfig);
|
||||
|
||||
var result = await _serviceConfigService.Get(_id.ToString());
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,9 @@ namespace adas_core.Test.Services;
|
||||
[TestFixture]
|
||||
public class TreatmentServiceTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the mock dependencies and creates a <see cref="TreatmentService"/> instance for unit testing.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
@@ -172,6 +175,10 @@ public class TreatmentServiceTest
|
||||
}
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that saving an <see cref="ApiRequest"/> without the Case option throws an <see cref="ApiRequestException"/>, preventing the insert operation.
|
||||
/// </summary>
|
||||
/// <exception cref="ApiRequestException">Thrown by the service when the Case option is not provided in the request.</exception>
|
||||
[Test]
|
||||
public void SaveRequest_Not_Case_option_Return_not_insert()
|
||||
{
|
||||
@@ -181,6 +188,9 @@ public class TreatmentServiceTest
|
||||
Assert.ThrowsAsync<ApiRequestException>(act);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that _treatmentService.SaveRequest throws an <see cref="ApiRequestException"/> when the <see cref="ApiRequest"/> is missing both the patient number and the point of care, preventing insertion of an incomplete request.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void SaveRequest_patientNumber_and_pointOfCare_null_Return_not_insert()
|
||||
{
|
||||
@@ -194,6 +204,9 @@ public class TreatmentServiceTest
|
||||
Assert.ThrowsAsync<ApiRequestException>(act);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that _treatmentService.SaveRequest does not insert a patient treatment record when the patient cannot be found in the archive.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task SaveRequest_Not_Find_Patient_Return_not_insert()
|
||||
{
|
||||
@@ -219,6 +232,9 @@ public class TreatmentServiceTest
|
||||
_treatmentArchiveRepositoryMock.Verify(d => d.InsertOneAsync(It.IsAny<PatientTreatment>()), Times.Never);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that SaveRequest does not insert a new patient treatment into the treatment archive when an existing patient is found by patient number.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task SaveRequest_Find_Patient_Return_insert()
|
||||
{
|
||||
@@ -255,6 +271,9 @@ public class TreatmentServiceTest
|
||||
_treatmentArchiveRepositoryMock.Verify(d => d.InsertOneAsync(It.IsAny<PatientTreatment>()), Times.Never);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>GetActiveTreatmentsByPatient</c> retrieves the full set of active treatments for the specified patient, returning a non-empty collection that includes all expected treatment records identified by their placer order entity identifiers.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetActiveTreatmentsByPatient()
|
||||
{
|
||||
@@ -272,6 +291,7 @@ public class TreatmentServiceTest
|
||||
That(result.Find(t => t?.PlacerOrder?.EntityIdentifier == "2100"), Is.Not.Null);
|
||||
That(result.Find(t => t?.PlacerOrder?.EntityIdentifier == "4590"), Is.Not.Null);
|
||||
That(result.Find(t => t?.PlacerOrder?.EntityIdentifier == "3690"), Is.Not.Null);
|
||||
};
|
||||
}
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,12 @@ using Moq;
|
||||
|
||||
namespace adas_core.Test.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Provides a unit test class for testing the functionality of the UnitService.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class is intended to contain test methods that validate the behavior and correctness of the UnitService.
|
||||
/// </remarks>
|
||||
public class UnitServiceTest
|
||||
{
|
||||
private readonly Mock<ILocalAuditService> _auditServiceMock = new();
|
||||
@@ -25,6 +31,10 @@ public class UnitServiceTest
|
||||
private Mock<IUnitRepository> _unitRepositoryMock = null!;
|
||||
private UnitService _unitService = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes mocked dependencies and a configured <see cref="UnitService"/> instance for each test,
|
||||
/// including a mock <see cref="HttpContext"/> with a test user claim.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
@@ -59,6 +69,9 @@ public class UnitServiceTest
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the unit service returns all units retrieved from the repository, including the correct count and content.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetAll_ShouldReturnAllUnits()
|
||||
{
|
||||
@@ -75,6 +88,9 @@ public class UnitServiceTest
|
||||
Assert.That(result, Is.EqualTo(units));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the Get method on the unit service returns the expected unit when a valid identifier is provided.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Get_ShouldReturnUnitById()
|
||||
{
|
||||
@@ -91,16 +107,19 @@ public class UnitServiceTest
|
||||
Assert.That(result, Is.EqualTo(unit));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the Get method retrieves a unit by name when the provided identifier is not a valid ObjectId, matching against either the unit's Title or Name.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Get_ShouldReturnUnitByName_WhenIdIsNotObjectId()
|
||||
{
|
||||
// Arrange
|
||||
var unitName = "TestUnit";
|
||||
var units = new List<Unit>
|
||||
{
|
||||
new() { Title = unitName },
|
||||
new() { Name = unitName }
|
||||
};
|
||||
{
|
||||
new() { Title = unitName },
|
||||
new() { Name = unitName }
|
||||
};
|
||||
_unitRepositoryMock.Setup(repo => repo.GetAll()).ReturnsAsync(units);
|
||||
|
||||
// Act
|
||||
@@ -111,16 +130,20 @@ public class UnitServiceTest
|
||||
Assert.That(result?.Title ?? result?.Name, Is.EqualTo(unitName));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that _unitService" returns all units retrieved from the repository,
|
||||
/// ensuring the result is not null, contains the expected number of units, and matches the source data.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetAllUnits_ShouldReturnAllUnits()
|
||||
{
|
||||
// Arrange
|
||||
var units = new List<Unit>
|
||||
{
|
||||
new() { Id = ObjectId.GenerateNewId(), Name = "Unit1" },
|
||||
new() { Id = ObjectId.GenerateNewId(), Name = "Unit2" }
|
||||
};
|
||||
{
|
||||
new() { Id = ObjectId.GenerateNewId(), Name = "Unit1" },
|
||||
new() { Id = ObjectId.GenerateNewId(), Name = "Unit2" }
|
||||
};
|
||||
|
||||
_unitRepositoryMock.Setup(repo => repo.GetAll()).ReturnsAsync(units);
|
||||
|
||||
@@ -133,6 +156,9 @@ public class UnitServiceTest
|
||||
Assert.That(result, Is.EquivalentTo(units));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that _unitService.FindById" returns the matching <see cref="Unit"/> when the repository locates it by id.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetUnitById_ShouldReturnUnit_WhenFound()
|
||||
{
|
||||
@@ -150,6 +176,9 @@ public class UnitServiceTest
|
||||
Assert.That(result, Is.EqualTo(unit));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>GetByName</c> returns the matching unit when a unit with the specified name exists in the repository.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetUnitByName_ShouldReturnUnit_WhenFound()
|
||||
{
|
||||
@@ -167,6 +196,9 @@ public class UnitServiceTest
|
||||
Assert.That(result, Is.EqualTo(expectedUnit));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <c>FindByPatientId</c> returns the associated unit when the patient is found in an active (in-use) point of care.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindUnitByPatientId_ShouldReturnUnit_WhenPatientFoundInActivePoC()
|
||||
{
|
||||
@@ -194,6 +226,9 @@ public class UnitServiceTest
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the unit service returns the matching units retrieved from the repository when a call is made to find units by the specified master list identifier and type.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindUnitsByMasterListId_ShouldReturnUnits_WhenUnitsFound()
|
||||
{
|
||||
@@ -216,18 +251,22 @@ public class UnitServiceTest
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the unit service returns the matching units when the repository contains units
|
||||
/// whose point of care matches the specified patient location.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByLocation_ShouldReturnUnits_WhenUnitsFound()
|
||||
{
|
||||
// Arrange
|
||||
var location = new PatientLocation("TestUnit", "TestBed", "TestRoom");
|
||||
var units = new List<Unit>
|
||||
{
|
||||
new()
|
||||
{
|
||||
PointOfCares = [new PointOfCare { UnitName = "TestUnit", Bed = "TestBed" }]
|
||||
}
|
||||
};
|
||||
new()
|
||||
{
|
||||
PointOfCares = [new PointOfCare { UnitName = "TestUnit", Bed = "TestBed" }]
|
||||
}
|
||||
};
|
||||
_unitRepositoryMock.Setup(repo => repo.GetAll()).ReturnsAsync(units);
|
||||
|
||||
// Act
|
||||
@@ -240,6 +279,9 @@ public class UnitServiceTest
|
||||
Assert.That(result?.First().PointOfCares?.First().Bed, Is.EqualTo("TestBed"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that FindByLocation returns an empty list when no units match the specified patient location.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByLocation_ShouldReturnEmptyList_WhenNoUnitsFound()
|
||||
{
|
||||
@@ -255,6 +297,10 @@ public class UnitServiceTest
|
||||
Assert.That(result?.Count, Is.EqualTo(0));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the unit service returns the expected unit when a valid unit identifier is provided.
|
||||
/// </summary>
|
||||
/// <returns>A task that represents the asynchronous test execution.</returns>
|
||||
[Test]
|
||||
public async Task FindById_ShouldReturnUnit_WhenValidIdProvided()
|
||||
{
|
||||
@@ -271,6 +317,10 @@ public class UnitServiceTest
|
||||
Assert.That(result, Is.EqualTo(expectedUnit));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the unit service's FindById method returns null when invoked with a null identifier,
|
||||
/// ensuring graceful handling of null input without throwing or returning a default entity.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindById_ShouldReturnNull_WhenNullIdProvided()
|
||||
{
|
||||
@@ -283,6 +333,9 @@ public class UnitServiceTest
|
||||
Assert.That(result, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that FindByName retrieves and returns the expected <c>Unit</c> when a valid unit name is provided.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FindByName_ShouldReturnUnit_WhenValidNameProvided()
|
||||
{
|
||||
@@ -300,6 +353,9 @@ public class UnitServiceTest
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the unit service correctly delegates the insert operation to the repository and returns the inserted unit entity unchanged.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task InsertOne_ShouldReturnInsertedUnit()
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,257 +7,311 @@ using MongoDB.Bson;
|
||||
|
||||
namespace adas_core.Test.Utilities;
|
||||
|
||||
/// <summary>
|
||||
/// Provides a collection of utility members to support testing operations and helper functionality.
|
||||
/// </summary>
|
||||
public class TestUtilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates and returns a fully populated, valid <see cref="PointOfCare"/> instance with predefined test values, typically used as a helper for unit testing or seeding sample data.
|
||||
/// </summary>
|
||||
/// <returns>A new <see cref="PointOfCare"/> object initialized with valid identifiers, room and bed information, an available status, a default configuration, and a referenced unit.</returns>
|
||||
public static PointOfCare CreateValidPointOfCare()
|
||||
{
|
||||
return new PointOfCare
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Room = "Test Room",
|
||||
Bed = "Test Bed",
|
||||
UnitId = ObjectId.GenerateNewId(),
|
||||
Configuration = new PointOfCareConfiguration(),
|
||||
Status = StatusEnum.PointOfCare.Available,
|
||||
AdmissionId = ObjectId.GenerateNewId(),
|
||||
Unit = CreateValidUnit(),
|
||||
UnitName = "Test Unit"
|
||||
};
|
||||
}
|
||||
return new PointOfCare
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Room = "Test Room",
|
||||
Bed = "Test Bed",
|
||||
UnitId = ObjectId.GenerateNewId(),
|
||||
Configuration = new PointOfCareConfiguration(),
|
||||
Status = StatusEnum.PointOfCare.Available,
|
||||
AdmissionId = ObjectId.GenerateNewId(),
|
||||
Unit = CreateValidUnit(),
|
||||
UnitName = "Test Unit"
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a valid <see cref="Discharge"/> instance populated with generated identifiers, current UTC timestamps, and default test values for use in test scenarios.
|
||||
/// </summary>
|
||||
/// <returns>A fully populated <see cref="Discharge"/> object with all required fields set to valid values.</returns>
|
||||
public static Discharge CreateValidDischarge()
|
||||
{
|
||||
return new Discharge
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PointOfCareId = ObjectId.GenerateNewId(),
|
||||
UnitId = ObjectId.GenerateNewId(),
|
||||
DischargeDate = DateTime.UtcNow,
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
Destination = "Test Destination",
|
||||
DestinationOption = CreateValidOptionList(),
|
||||
ServiceOption = CreateValidOptionList(),
|
||||
Service = "Test Service",
|
||||
MedicalDischarge = DateTime.UtcNow,
|
||||
AdminDischarge = DateTime.UtcNow,
|
||||
NurseDischarge = DateTime.UtcNow
|
||||
};
|
||||
}
|
||||
return new Discharge
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PointOfCareId = ObjectId.GenerateNewId(),
|
||||
UnitId = ObjectId.GenerateNewId(),
|
||||
DischargeDate = DateTime.UtcNow,
|
||||
PatientId = ObjectId.GenerateNewId(),
|
||||
Destination = "Test Destination",
|
||||
DestinationOption = CreateValidOptionList(),
|
||||
ServiceOption = CreateValidOptionList(),
|
||||
Service = "Test Service",
|
||||
MedicalDischarge = DateTime.UtcNow,
|
||||
AdminDischarge = DateTime.UtcNow,
|
||||
NurseDischarge = DateTime.UtcNow
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and returns a new <see cref="Patient"/> instance populated with valid test/default values, including a generated identifier, sample patient numbers, admission timestamp, and related option list entries for discharge status, altable, and origin.
|
||||
/// </summary>
|
||||
/// <returns>A fully initialized <see cref="Patient"/> object suitable for use in testing or seeding scenarios.</returns>
|
||||
public static Patient CreateValidPatient()
|
||||
{
|
||||
return new Patient
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientNumber = "TestPatientNumber",
|
||||
PatientId = "TestPatientId",
|
||||
AdmTime = DateTime.UtcNow,
|
||||
DischargeStatus = new OptionList
|
||||
return new Patient
|
||||
{
|
||||
OptionType = "TestDischargeStatus",
|
||||
Name = "TestDischargeStatusName",
|
||||
IconDefault = "TestIcon",
|
||||
Color = "TestColor",
|
||||
Description = "TestDescription",
|
||||
InitDate = DateTime.UtcNow,
|
||||
EndDate = DateTime.UtcNow.AddDays(7) // Example end date
|
||||
},
|
||||
Altable = new OptionList
|
||||
{
|
||||
OptionType = "TestAltable",
|
||||
Name = "TestAltableName",
|
||||
IconDefault = "TestAltableIcon",
|
||||
Color = "TestAltableColor",
|
||||
Description = "TestAltableDescription",
|
||||
InitDate = DateTime.UtcNow,
|
||||
EndDate = DateTime.UtcNow.AddDays(7) // Example end date
|
||||
},
|
||||
Origin = new OptionList
|
||||
{
|
||||
OptionType = "TestOrigin",
|
||||
Name = "TestOriginName",
|
||||
IconDefault = "TestOriginIcon",
|
||||
Color = "TestOriginColor",
|
||||
Description = "TestOriginDescription",
|
||||
InitDate = DateTime.UtcNow,
|
||||
EndDate = DateTime.UtcNow.AddDays(7) // Example end date
|
||||
}
|
||||
// Initialize other properties as needed
|
||||
};
|
||||
}
|
||||
|
||||
public static OptionList CreateValidOptionList()
|
||||
{
|
||||
return new OptionList
|
||||
{
|
||||
OptionType = "Test Option",
|
||||
Name = "Test Name",
|
||||
IconDefault = "Test Icon",
|
||||
Color = "Test Color",
|
||||
Description = "Test Description",
|
||||
InitDate = DateTime.UtcNow,
|
||||
EndDate = DateTime.UtcNow.AddDays(1)
|
||||
};
|
||||
}
|
||||
|
||||
private static PatientLocation CreateValidPatientLocation()
|
||||
{
|
||||
return new PatientLocation
|
||||
{
|
||||
UnitName = "Test Unit",
|
||||
Bed = "Test Bed",
|
||||
Room = "Test Room"
|
||||
};
|
||||
}
|
||||
|
||||
public static Unit CreateValidUnit()
|
||||
{
|
||||
return new Unit
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Title = "Test Unit",
|
||||
Name = "Test Unit",
|
||||
LastUpdate = null,
|
||||
PointOfCareIds = [],
|
||||
Status = StatusEnum.Type.Ok,
|
||||
Configuration = new UnitConfiguration
|
||||
{
|
||||
AutoAdt = true,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Admission CreateValidAdmission()
|
||||
{
|
||||
return new Admission
|
||||
{
|
||||
//Id = ObjectId.GenerateNewId(),
|
||||
AdmissionDate = DateTime.UtcNow,
|
||||
Nhc = ObjectId.GenerateNewId().ToString(),
|
||||
UnitId = ObjectId.GenerateNewId(),
|
||||
PointOfCareId = ObjectId.GenerateNewId(),
|
||||
Person = new Person
|
||||
{
|
||||
FirstName = "Test First Name",
|
||||
LastName = "Test Last Name"
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
PatientNumber = "TestPatientNumber",
|
||||
PatientId = "TestPatientId",
|
||||
AdmTime = DateTime.UtcNow,
|
||||
DischargeStatus = new OptionList
|
||||
{
|
||||
OptionType = "TestDischargeStatus",
|
||||
Name = "TestDischargeStatusName",
|
||||
IconDefault = "TestIcon",
|
||||
Color = "TestColor",
|
||||
Description = "TestDescription",
|
||||
InitDate = DateTime.UtcNow,
|
||||
EndDate = DateTime.UtcNow.AddDays(7) // Example end date
|
||||
},
|
||||
Altable = new OptionList
|
||||
{
|
||||
OptionType = "TestAltable",
|
||||
Name = "TestAltableName",
|
||||
IconDefault = "TestAltableIcon",
|
||||
Color = "TestAltableColor",
|
||||
Description = "TestAltableDescription",
|
||||
InitDate = DateTime.UtcNow,
|
||||
EndDate = DateTime.UtcNow.AddDays(7) // Example end date
|
||||
},
|
||||
Origin = new OptionList
|
||||
{
|
||||
OptionType = "TestOrigin",
|
||||
Name = "TestOriginName",
|
||||
IconDefault = "TestOriginIcon",
|
||||
Color = "TestOriginColor",
|
||||
Description = "TestOriginDescription",
|
||||
InitDate = DateTime.UtcNow,
|
||||
EndDate = DateTime.UtcNow.AddDays(7) // Example end date
|
||||
}
|
||||
// Initialize other properties as needed
|
||||
},
|
||||
Origin = CreateValidOptionList(),
|
||||
OriginAux = "Test Origin Aux",
|
||||
Diagnosis = CreateValidOptionList(),
|
||||
DiagnosisAux = "Test Diagnosis Aux",
|
||||
Allergies =
|
||||
[
|
||||
CreateValidOptionList(),
|
||||
CreateValidOptionList()
|
||||
// Add more allergies as needed
|
||||
],
|
||||
Insulation = CreateValidOptionList(),
|
||||
LanguageBarrier = [CreateValidOptionList()],
|
||||
PatientLocation = CreateValidPatientLocation()
|
||||
// Initialize other properties as needed
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="OptionList"/> instance populated with predefined valid test values, typically used as a helper for unit tests or test data seeding.
|
||||
/// </summary>
|
||||
/// <returns>An <see cref="OptionList"/> with sample values, where <c>InitDate</c> is set to the current UTC time and <c>EndDate</c> is set to one day after the current UTC time.</returns>
|
||||
public static OptionList CreateValidOptionList()
|
||||
{
|
||||
return new OptionList
|
||||
{
|
||||
OptionType = "Test Option",
|
||||
Name = "Test Name",
|
||||
IconDefault = "Test Icon",
|
||||
Color = "Test Color",
|
||||
Description = "Test Description",
|
||||
InitDate = DateTime.UtcNow,
|
||||
EndDate = DateTime.UtcNow.AddDays(1)
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a valid <see cref="PatientLocation"/> instance populated with default test data for use in test scenarios.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="PatientLocation"/> with predefined unit name, bed, and room values.</returns>
|
||||
private static PatientLocation CreateValidPatientLocation()
|
||||
{
|
||||
return new PatientLocation
|
||||
{
|
||||
UnitName = "Test Unit",
|
||||
Bed = "Test Bed",
|
||||
Room = "Test Room"
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="Unit"/> instance populated with valid default values, typically used for testing or seeding purposes.
|
||||
/// </summary>
|
||||
/// <returns>A new <see cref="Unit"/> object with a generated unique identifier, default title and name, no last update timestamp, an empty list of point of care IDs, an OK status, and a configuration with auto ADT enabled.</returns>
|
||||
public static Unit CreateValidUnit()
|
||||
{
|
||||
return new Unit
|
||||
{
|
||||
Id = ObjectId.GenerateNewId(),
|
||||
Title = "Test Unit",
|
||||
Name = "Test Unit",
|
||||
LastUpdate = null,
|
||||
PointOfCareIds = [],
|
||||
Status = StatusEnum.Type.Ok,
|
||||
Configuration = new UnitConfiguration
|
||||
{
|
||||
AutoAdt = true,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and returns a valid <see cref="Admission"/> instance populated with sample test data, including generated unique identifiers, a test person, option lists for origin, diagnosis, insulation, language barrier, allergies, and a patient location.
|
||||
/// </summary>
|
||||
/// <returns>A new <see cref="Admission"/> object fully initialized with valid test values.</returns>
|
||||
public static Admission CreateValidAdmission()
|
||||
{
|
||||
return new Admission
|
||||
{
|
||||
//Id = ObjectId.GenerateNewId(),
|
||||
AdmissionDate = DateTime.UtcNow,
|
||||
Nhc = ObjectId.GenerateNewId().ToString(),
|
||||
UnitId = ObjectId.GenerateNewId(),
|
||||
PointOfCareId = ObjectId.GenerateNewId(),
|
||||
Person = new Person
|
||||
{
|
||||
FirstName = "Test First Name",
|
||||
LastName = "Test Last Name"
|
||||
// Initialize other properties as needed
|
||||
},
|
||||
Origin = CreateValidOptionList(),
|
||||
OriginAux = "Test Origin Aux",
|
||||
Diagnosis = CreateValidOptionList(),
|
||||
DiagnosisAux = "Test Diagnosis Aux",
|
||||
Allergies =
|
||||
[
|
||||
CreateValidOptionList(),
|
||||
CreateValidOptionList()
|
||||
// Add more allergies as needed
|
||||
],
|
||||
Insulation = CreateValidOptionList(),
|
||||
LanguageBarrier = [CreateValidOptionList()],
|
||||
PatientLocation = CreateValidPatientLocation()
|
||||
// Initialize other properties as needed
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a valid <see cref="CardConfig"/> instance with a default structure consisting of a single row containing one <see cref="DisplayConfigEnums.CellType.DemographicCell"/> wrapped in a <see cref="DisplayConfigEnums.CellType.CellWrapper"/> with a grow priority of 1.
|
||||
/// </summary>
|
||||
/// <param name="id">The optional identifier for the configuration. If <c>null</c>, a new <see cref="ObjectId"/> is generated.</param>
|
||||
/// <returns>A newly created <see cref="CardConfig"/> populated with the default valid configuration.</returns>
|
||||
public static CardConfig CreateValidCardConfig(ObjectId? id = null)
|
||||
{
|
||||
return new CardConfig
|
||||
{
|
||||
Id = id ?? ObjectId.GenerateNewId(),
|
||||
Rows = new List<RowCardConfig>
|
||||
return new CardConfig
|
||||
{
|
||||
new()
|
||||
Id = id ?? ObjectId.GenerateNewId(),
|
||||
Rows = new List<RowCardConfig>
|
||||
{
|
||||
Cells = new List<Cell>
|
||||
new()
|
||||
{
|
||||
new() { Type = DisplayConfigEnums.CellType.DemographicCell }
|
||||
},
|
||||
GrowPriority = 1,
|
||||
Type = DisplayConfigEnums.CellType.CellWrapper
|
||||
Cells = new List<Cell>
|
||||
{
|
||||
new() { Type = DisplayConfigEnums.CellType.DemographicCell }
|
||||
},
|
||||
GrowPriority = 1,
|
||||
Type = DisplayConfigEnums.CellType.CellWrapper
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a valid <see cref="CardDetailsConfig"/> instance configured for the nurse display, including a demographic row containing allergy and demographic cells. If no identifier is supplied, a new <see cref="ObjectId"/> is generated.
|
||||
/// </summary>
|
||||
/// <param name="id">The optional identifier to assign to the configuration. When <c>null</c>, a new <see cref="ObjectId"/> is generated.</param>
|
||||
/// <returns>A <see cref="CardDetailsConfig"/> populated with the nurse display configuration.</returns>
|
||||
public static CardDetailsConfig CreateValidCardDetailsNurseConfig(ObjectId? id = null)
|
||||
{
|
||||
return new CardDetailsConfig
|
||||
{
|
||||
Id = id ?? ObjectId.GenerateNewId(),
|
||||
NurseRows = new List<RowDetailsConfig>
|
||||
return new CardDetailsConfig
|
||||
{
|
||||
new()
|
||||
Id = id ?? ObjectId.GenerateNewId(),
|
||||
NurseRows = new List<RowDetailsConfig>
|
||||
{
|
||||
Type = DisplayConfigEnums.RowType.Demographic,
|
||||
Title = "Title details",
|
||||
Cells = new List<CellDetails>
|
||||
new()
|
||||
{
|
||||
new()
|
||||
Type = DisplayConfigEnums.RowType.Demographic,
|
||||
Title = "Title details",
|
||||
Cells = new List<CellDetails>
|
||||
{
|
||||
Type = DisplayConfigEnums.CellType.CellWrapper,
|
||||
Cells = new List<CellDetails>
|
||||
new()
|
||||
{
|
||||
new()
|
||||
Type = DisplayConfigEnums.CellType.CellWrapper,
|
||||
Cells = new List<CellDetails>
|
||||
{
|
||||
Type = DisplayConfigEnums.CellType.AllergyCell
|
||||
},
|
||||
new()
|
||||
{
|
||||
Type = DisplayConfigEnums.CellType.DemographicCell
|
||||
new()
|
||||
{
|
||||
Type = DisplayConfigEnums.CellType.AllergyCell
|
||||
},
|
||||
new()
|
||||
{
|
||||
Type = DisplayConfigEnums.CellType.DemographicCell
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a valid <see cref="CardDetailsConfig"/> instance populated with a default smart section layout, including a general row that contains beacon color and isolation observations. If no identifier is supplied, a new <see cref="ObjectId"/> is generated for the configuration.
|
||||
/// </summary>
|
||||
/// <param name="id">The optional identifier to assign to the configuration. When <c>null</c>, a new <see cref="ObjectId"/> is generated.</param>
|
||||
/// <returns>A <see cref="CardDetailsConfig"/> configured with a predefined smart section layout.</returns>
|
||||
public static CardDetailsConfig CreateValidCardDetailsSmartConfig(ObjectId? id = null)
|
||||
{
|
||||
return new CardDetailsConfig
|
||||
{
|
||||
Id = id ?? ObjectId.GenerateNewId(),
|
||||
SmartSections = new List<SectionBoxLayout>
|
||||
return new CardDetailsConfig
|
||||
{
|
||||
new()
|
||||
Id = id ?? ObjectId.GenerateNewId(),
|
||||
SmartSections = new List<SectionBoxLayout>
|
||||
{
|
||||
Type = DisplayConfigEnums.RowType.General,
|
||||
Name = "Title details",
|
||||
Rows = new List<RowBoxLayout>
|
||||
new()
|
||||
{
|
||||
new()
|
||||
Type = DisplayConfigEnums.RowType.General,
|
||||
Name = "Title details",
|
||||
Rows = new List<RowBoxLayout>
|
||||
{
|
||||
Type = DisplayConfigEnums.CellType.CellWrapper,
|
||||
Observations = new List<ObservationRowBoxLayout>
|
||||
new()
|
||||
{
|
||||
new()
|
||||
Type = DisplayConfigEnums.CellType.CellWrapper,
|
||||
Observations = new List<ObservationRowBoxLayout>
|
||||
{
|
||||
Type = DisplayConfigEnums.CellType.BeaconColor
|
||||
},
|
||||
new()
|
||||
{
|
||||
Type = DisplayConfigEnums.CellType.Isolation
|
||||
new()
|
||||
{
|
||||
Type = DisplayConfigEnums.CellType.BeaconColor
|
||||
},
|
||||
new()
|
||||
{
|
||||
Type = DisplayConfigEnums.CellType.Isolation
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a valid <see cref="DisplayConfig"/> instance, generating new <see cref="ObjectId"/> values for any ID parameters that are <c>null</c>. Intended for use in test scenarios.
|
||||
/// </summary>
|
||||
/// <param name="type">The display type to assign to the configuration.</param>
|
||||
/// <param name="id">The optional identifier for the display config. A new <see cref="ObjectId"/> is generated when <c>null</c>.</param>
|
||||
/// <param name="idCard">The optional card config identifier. A new <see cref="ObjectId"/> is generated when <c>null</c>.</param>
|
||||
/// <param name="idDetail">The optional detail config identifier. A new <see cref="ObjectId"/> is generated when <c>null</c>.</param>
|
||||
/// <returns>A fully populated <see cref="DisplayConfig"/> with default field and hospital values.</returns>
|
||||
public static DisplayConfig CreateValidDisplayConfig(DisplayConfigEnums.DisplayType type, ObjectId? id,
|
||||
ObjectId? idCard, ObjectId? idDetail)
|
||||
{
|
||||
return new DisplayConfig
|
||||
ObjectId? idCard, ObjectId? idDetail)
|
||||
{
|
||||
Id = id ?? ObjectId.GenerateNewId(),
|
||||
CardConfigId = idCard ?? ObjectId.GenerateNewId(),
|
||||
DetailConfigId = idDetail ?? ObjectId.GenerateNewId(),
|
||||
Type = type,
|
||||
FieldList = new List<Field> { new() { Name = "FR", Last = 2 } },
|
||||
Hospital = "Test Hospital"
|
||||
};
|
||||
}
|
||||
return new DisplayConfig
|
||||
{
|
||||
Id = id ?? ObjectId.GenerateNewId(),
|
||||
CardConfigId = idCard ?? ObjectId.GenerateNewId(),
|
||||
DetailConfigId = idDetail ?? ObjectId.GenerateNewId(),
|
||||
Type = type,
|
||||
FieldList = new List<Field> { new() { Name = "FR", Last = 2 } },
|
||||
Hospital = "Test Hospital"
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user