Files
adas-core/adas-core.Test/Services/PatientServiceTest.cs
2026-06-26 10:29:23 +02:00

2565 lines
107 KiB
C#

using System.Security.Claims;
using adas_core.Application.Repositories.Interfaces;
using adas_core.Application.Services;
using adas_core.Application.Services.Interfaces;
using adas_core.Application.Subscriptions;
using adas_core.Domain.Enums;
using adas_core.Domain.Models;
using adas_core.Domain.Models.AppSettings;
using adas_core.Domain.Models.Masters;
using adas_core.Domain.Models.MongoModels;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MongoDB.Bson;
using Moq;
using Options = Microsoft.Extensions.Options.Options;
using static NUnit.Framework.Assert;
namespace adas_core.Test.Services;
[TestFixture]
internal class PatientServiceTest
{
/// <summary>
/// Initializes the test environment for PatientService unit tests by creating mock instances of all required
/// dependencies and pre-configuring common lookup scenarios for units and points of care, including virtual
/// point of care states (Pushed, Moved, Deleted, Cancelled, Recovered, Unknown) used across test cases.
/// </summary>
[SetUp]
public void Setup()
{
_admissionService = new Mock<IAdmissionService>();
_patientRepositoryMock = new Mock<IPatientRepository>();
_patientArchiveRepository = new Mock<IPatientArchiveRepository>();
_poCMappingServiceMock = new Mock<IPoCMappingService>();
var treatmentServiceMock = new Mock<ITreatmentService>();
_treatServiceLazy = new Lazy<ITreatmentService>(() => treatmentServiceMock.Object);
var observationServiceMock = new Mock<IObservationService>();
_observationServiceLazy = new Lazy<IObservationService>(() => observationServiceMock.Object);
_diagnosisServiceMock = new Mock<IDiagnosisService>();
_appointmentServiceMock = new Mock<IAppointmentService>();
var pumpServiceMock = new Mock<IPumpService>();
_pumpServiceLazy = new Lazy<IPumpService>(() => pumpServiceMock.Object);
_recordingAlertService = new Mock<IRecordingAlertService>();
_dischargeService = new Mock<IDischargeService> { CallBase = true };
_unitService = new Mock<IUnitService> { CallBase = true };
_displayservice = new Mock<IDisplayService> { CallBase = true };
_pocService = new Mock<IPointOfCareService> { CallBase = true };
_optionsApiSettings = Options.Create(_apiSettings);
_listSettings = Options.Create(new ListSettings());
_logger = new Mock<ILogger<PatientService>>();
_clientMessageServiceMock = new Mock<IClientMessageService>();
_subscribersServiceMock = new Mock<ISubscribersService>();
_subscriberGroupedServiceMock = new Mock<ISubscriberGroupedService>();
_lazyAdmissionService = new Lazy<IAdmissionService>(() => _admissionService.Object);
_displayConfigServiceMock = new Mock<IDisplayConfigService>();
_groupedServiceMock = new Mock<IGroupedObservationService>();
_patientCarePlanServiceMock = new Mock<IPatientCarePlanService>();
var subscribers = new List<WsSubscriber>();
// Set up the mock object to return a specific value when a method is called
_subscribersServiceMock.Setup(x => x.GetSubscribers()).Returns(subscribers);
var userClaims = new ClaimsPrincipal(new ClaimsIdentity([
new Claim(ClaimTypes.Name, "TestUser")
], "mock"));
var httpContextMock = new DefaultHttpContext
{
User = userClaims
};
_masterListMock = new Mock<IMasterListServiceFactory>();
_httpContextAccessorMock.Setup(accessor => accessor.HttpContext)
.Returns(httpContextMock);
_patientService = new PatientService(
_patientRepositoryMock.Object,
_patientArchiveRepository.Object,
_observationServiceLazy,
_treatServiceLazy,
_poCMappingServiceMock.Object,
_diagnosisServiceMock.Object,
_appointmentServiceMock.Object,
_pumpServiceLazy,
_recordingAlertService.Object,
_dischargeService.Object,
_optionsApiSettings,
_listSettings,
_logger.Object,
_clientMessageServiceMock.Object,
_subscribersServiceMock.Object,
_subscriberGroupedServiceMock.Object,
_unitService.Object,
_displayservice.Object,
_pocService.Object,
_lazyAdmissionService,
_displayConfigServiceMock.Object,
_groupedServiceMock.Object,
_patientCarePlanServiceMock.Object,
_httpContextAccessorMock.Object,
_auditServiceMock.Object,
_masterListMock.Object
);
var unit = new Unit
{
Id = _unitId,
Name = "UCI5C",
Title = "CONTROLC",
Configuration = new UnitConfiguration
{
AutoAdt = true
}
};
_unitService.Setup(u => u.FindByName(unit.Name)).ReturnsAsync(unit);
_unitService.Setup(u => u.FindById(unit.Id)).ReturnsAsync(unit);
var pocCinna1 = new PointOfCare
{
Id = _pocCinna01Id,
UnitId = _unitId,
Room = "CINA01",
Bed = "CINA01",
Status = StatusEnum.PointOfCare.InUse
};
var pocCinna2 = new PointOfCare
{
Id = _pocCinna02Id,
UnitId = _unitId,
Room = "CINA02",
Bed = "CINA02",
Status = StatusEnum.PointOfCare.InUse
};
var pocCinna3 = new PointOfCare
{
Id = _pocCinna03Id,
UnitId = _unitId,
Room = "CINA03",
Bed = "CINA03",
Status = StatusEnum.PointOfCare.InUse
};
var pocCinna4 = new PointOfCare
{
Id = _pocCinna03Id,
UnitId = _unitId,
Room = "CINA04",
Bed = "CINA04",
Status = StatusEnum.PointOfCare.InUse
};
var pocPushed = new PointOfCare
{
Id = _pocPushedId,
UnitId = _unitId,
Room = VirtualPointOfCare.Pushed.ToString(),
Bed = VirtualPointOfCare.Pushed.ToString()
};
var pocMoved = new PointOfCare
{
Id = _pocMovedId,
UnitId = _unitId,
Room = VirtualPointOfCare.Moved.ToString(),
Bed = VirtualPointOfCare.Moved.ToString()
};
var pocDeleted = new PointOfCare
{
Id = _pocDeletedId,
UnitId = _unitId,
Room = VirtualPointOfCare.Deleted.ToString(),
Bed = VirtualPointOfCare.Deleted.ToString()
};
var pocCanceled = new PointOfCare
{
Id = _pocCanceledId,
UnitId = _unitId,
Room = VirtualPointOfCare.Cancelled.ToString(),
Bed = VirtualPointOfCare.Cancelled.ToString()
};
var pocRecovered = new PointOfCare
{
Id = _pocRecoveredId,
UnitId = _unitId,
Room = VirtualPointOfCare.Recovered.ToString(),
Bed = VirtualPointOfCare.Recovered.ToString()
};
var pocUnknown = new PointOfCare
{
Id = _pocUnknowndId,
UnitId = _unitId,
Room = VirtualPointOfCare.Unknown.ToString(),
Bed = VirtualPointOfCare.Unknown.ToString()
};
// Find By Bed And Unit
_pocService.Setup(poc => poc.FindByBedAndUnitId("CINA01", unit.Id)).ReturnsAsync(pocCinna1);
_pocService.Setup(poc => poc.FindByBedAndUnitId("CINA02", unit.Id)).ReturnsAsync(pocCinna2);
_pocService.Setup(poc => poc.FindByBedAndUnitId("CINA03", unit.Id)).ReturnsAsync(pocCinna3);
_pocService.Setup(poc => poc.FindByBedAndUnitId("CINA04", unit.Id)).ReturnsAsync(pocCinna4);
_pocService.Setup(poc => poc.FindByBedAndUnitId(VirtualPointOfCare.Pushed.ToString(), unit.Id))
.ReturnsAsync(pocPushed);
_pocService.Setup(poc => poc.FindByBedAndUnitId(VirtualPointOfCare.Moved.ToString(), unit.Id))
.ReturnsAsync(pocMoved);
_pocService.Setup(poc => poc.FindByBedAndUnitId(VirtualPointOfCare.Deleted.ToString(), unit.Id))
.ReturnsAsync(pocDeleted);
_pocService.Setup(poc => poc.FindByBedAndUnitId(VirtualPointOfCare.Cancelled.ToString(), unit.Id))
.ReturnsAsync(pocCanceled);
_pocService.Setup(poc => poc.FindByBedAndUnitId(VirtualPointOfCare.Recovered.ToString(), unit.Id))
.ReturnsAsync(pocRecovered);
_pocService.Setup(poc => poc.FindByBedAndUnitId(VirtualPointOfCare.Unknown.ToString(), unit.Id))
.ReturnsAsync(pocUnknown);
// Find By ID
_pocService.Setup(poc => poc.FindById(_pocCinna01Id)).ReturnsAsync(pocCinna1);
_pocService.Setup(poc => poc.FindById(_pocCinna02Id)).ReturnsAsync(pocCinna2);
_pocService.Setup(poc => poc.FindById(_pocCinna03Id)).ReturnsAsync(pocCinna3);
_pocService.Setup(poc => poc.FindById(_pocCinna04Id)).ReturnsAsync(pocCinna4);
_pocService.Setup(poc => poc.FindById(pocPushed.Id)).ReturnsAsync(pocPushed);
_pocService.Setup(poc => poc.FindById(pocMoved.Id)).ReturnsAsync(pocMoved);
_pocService.Setup(poc => poc.FindById(pocDeleted.Id)).ReturnsAsync(pocDeleted);
_pocService.Setup(poc => poc.FindById(pocCanceled.Id)).ReturnsAsync(pocCanceled);
_pocService.Setup(poc => poc.FindById(pocRecovered.Id)).ReturnsAsync(pocRecovered);
_pocService.Setup(poc => poc.FindById(pocUnknown.Id)).ReturnsAsync(pocUnknown);
// GetByCodeSysAndCode Info
_pocService.Setup(poc => poc.GetInfo(_pocCinna01Id, It.IsAny<LocaleEnum?>(), It.IsAny<bool>(), It.IsAny<CancellationToken>())).ReturnsAsync(pocCinna1);
_pocService.Setup(poc => poc.GetInfo(_pocCinna02Id, It.IsAny<LocaleEnum?>(), It.IsAny<bool>(), It.IsAny<CancellationToken>())).ReturnsAsync(pocCinna2);
_pocService.Setup(poc => poc.GetInfo(_pocCinna03Id, It.IsAny<LocaleEnum?>(), It.IsAny<bool>(), It.IsAny<CancellationToken>())).ReturnsAsync(pocCinna3);
_pocService.Setup(poc => poc.GetInfo(_pocCinna04Id, It.IsAny<LocaleEnum?>(), It.IsAny<bool>(), It.IsAny<CancellationToken>())).ReturnsAsync(pocCinna4);
_pocService.Setup(poc => poc.GetInfo(_pocPushedId, It.IsAny<LocaleEnum?>(), It.IsAny<bool>(), It.IsAny<CancellationToken>())).ReturnsAsync(pocPushed);
_pocService.Setup(poc => poc.GetInfo(_pocMovedId, It.IsAny<LocaleEnum?>(), It.IsAny<bool>(), It.IsAny<CancellationToken>())).ReturnsAsync(pocMoved);
_pocService.Setup(poc => poc.GetInfo(_pocDeletedId, It.IsAny<LocaleEnum?>(), It.IsAny<bool>(), It.IsAny<CancellationToken>())).ReturnsAsync(pocDeleted);
_pocService.Setup(poc => poc.GetInfo(_pocCanceledId, It.IsAny<LocaleEnum?>(), It.IsAny<bool>(), It.IsAny<CancellationToken>())).ReturnsAsync(pocCanceled);
_pocService.Setup(poc => poc.GetInfo(_pocRecoveredId, It.IsAny<LocaleEnum?>(), It.IsAny<bool>(), It.IsAny<CancellationToken>())).ReturnsAsync(pocRecovered);
_pocService.Setup(poc => poc.GetInfo(_pocUnknowndId, It.IsAny<LocaleEnum?>(), It.IsAny<bool>(), It.IsAny<CancellationToken>())).ReturnsAsync(pocUnknown);
// GetByCodeSysAndCode All
_pocService.Setup(poc => poc.GetAll()).ReturnsAsync([
pocCinna1, pocCinna2, pocCinna3, pocCinna4, pocPushed, pocMoved, pocDeleted, pocCanceled, pocRecovered,
pocUnknown
]);
_pocService.Setup(poc => poc.GetAllLocationInfo()).ReturnsAsync([
pocCinna1, pocCinna2, pocCinna3, pocCinna4, pocPushed, pocMoved, pocDeleted, pocCanceled, pocRecovered,
pocUnknown
]);
_unitService.Setup(poc => poc.GetAll(It.IsAny<bool>())).ReturnsAsync([unit]);
}
private PatientService _patientService = null!;
private Mock<IPatientRepository> _patientRepositoryMock = null!;
private Mock<IPoCMappingService> _poCMappingServiceMock = null!;
private Mock<IDiagnosisService> _diagnosisServiceMock = null!;
private Mock<IAppointmentService> _appointmentServiceMock = null!;
private Lazy<IPumpService> _pumpServiceLazy = null!;
private Mock<IPatientArchiveRepository> _patientArchiveRepository = null!;
private Lazy<IObservationService> _observationServiceLazy = null!;
private Lazy<ITreatmentService> _treatServiceLazy = null!;
private Mock<IRecordingAlertService> _recordingAlertService = null!;
private Mock<IDischargeService> _dischargeService = null!;
private Mock<IUnitService> _unitService = null!;
private Mock<IDisplayService> _displayservice = null!;
private Mock<IPointOfCareService> _pocService = null!;
private Mock<IDisplayConfigService> _displayConfigServiceMock = null!;
private Mock<IGroupedObservationService> _groupedServiceMock = null!;
private Mock<IPatientCarePlanService> _patientCarePlanServiceMock = null!;
private readonly Mock<IHttpContextAccessor> _httpContextAccessorMock = new();
private readonly Mock<ILocalAuditService> _auditServiceMock = new();
private IMock<IMasterListServiceFactory> _masterListMock = null!;
private readonly ApiSettings _apiSettings = new()
{
IccaFacility = "Philips.CIS.CVC",
CreatePatientWithOru = false,
UpdatePatientDataWithAdtA02 = true
};
private IOptions<ApiSettings> _optionsApiSettings = null!;
private IOptions<ListSettings> _listSettings = null!;
private Mock<ILogger<PatientService>> _logger = null!;
private Mock<IClientMessageService> _clientMessageServiceMock = null!;
private Mock<ISubscribersService> _subscribersServiceMock = null!;
private Mock<ISubscriberGroupedService> _subscriberGroupedServiceMock = null!;
private Lazy<IAdmissionService> _lazyAdmissionService = null!;
private Mock<IAdmissionService> _admissionService = null!;
private readonly ObjectId _unitId = ObjectId.GenerateNewId();
private readonly ObjectId _pocCinna01Id = ObjectId.GenerateNewId();
private readonly ObjectId _pocCinna02Id = ObjectId.GenerateNewId();
private readonly ObjectId _pocCinna03Id = ObjectId.GenerateNewId();
private readonly ObjectId _pocCinna04Id = ObjectId.GenerateNewId();
private readonly ObjectId _pocPushedId = ObjectId.GenerateNewId();
private readonly ObjectId _pocMovedId = ObjectId.GenerateNewId();
private readonly ObjectId _pocDeletedId = ObjectId.GenerateNewId();
private readonly ObjectId _pocCanceledId = ObjectId.GenerateNewId();
private readonly ObjectId _pocRecoveredId = ObjectId.GenerateNewId();
private readonly ObjectId _pocUnknowndId = ObjectId.GenerateNewId();
/// <summary>
/// Verifies that the patient service correctly retrieves a patient from the database by matching the patient number supplied in the API request, returning a patient populated with the expected unit, point of care, and patient number values.
/// </summary>
[Test]
public async Task Find_Patient_By_APIRequest_Get_Patient_By_PatientNumber()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var apiRequest = new ApiRequest
{
Type = "ORU_R01",
PatientNumber = patientNumber,
Patient = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(),
Gender = PatientEnum.Gender.Male
},
Location = location,
Facility = "Philips.CIS.CVC"
};
var patientInBd = new Patient
{
UnitId = _unitId,
PointOfCareId = _pocCinna02Id,
PatientNumber = patientNumber,
Person = new Person
{
FirstName = "Miguel",
LastName = "Villanueva",
BirthDate = new DateTime(),
Gender = PatientEnum.Gender.Male
}
};
_patientRepositoryMock.Setup(p => p.FindByPatientNumber(patientNumber)).ReturnsAsync(patientInBd);
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
var patient = await _patientService.FindPatientByApiRequest(apiRequest);
That(patient, Is.Not.Null);
using (Assert.EnterMultipleScope())
{
That(patient!.PatientNumber, Is.EqualTo("12345"));
That(patient.PointOfCareId!.Value, Is.EqualTo((ObjectId?)_pocCinna02Id));
};
}
/// <summary>
/// Verifies that <see cref="PatientService.FindPatientByApiRequest"/> creates a new patient record
/// when the requested patient does not exist and the <c>CreatePatientWithOru</c> option is set to <c>true</c>.
/// </summary>
[Test]
public async Task Find_Patient_By_APIRequest_Not_Exists_CreatePatientWithORU_True_Created_Patient()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var apiRequest = new ApiRequest
{
Type = "ORU_R01",
PatientNumber = patientNumber,
Patient = person,
Location = location,
Facility = "Philips.CIS.CVC"
};
_optionsApiSettings.Value.CreatePatientWithOru = true;
var patientService = new PatientService(
_patientRepositoryMock.Object,
_patientArchiveRepository.Object,
_observationServiceLazy,
_treatServiceLazy,
_poCMappingServiceMock.Object,
_diagnosisServiceMock.Object,
_appointmentServiceMock.Object,
_pumpServiceLazy,
_recordingAlertService.Object,
_dischargeService.Object,
_optionsApiSettings,
_listSettings,
_logger.Object,
_clientMessageServiceMock.Object,
_subscribersServiceMock.Object,
_subscriberGroupedServiceMock.Object,
_unitService.Object,
_displayservice.Object,
_pocService.Object,
_lazyAdmissionService,
_displayConfigServiceMock.Object,
_groupedServiceMock.Object,
_patientCarePlanServiceMock.Object,
_httpContextAccessorMock.Object,
_auditServiceMock.Object,
_masterListMock.Object
);
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
var patient = await patientService.FindPatientByApiRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.InsertOneAsync(It.Is<Patient>(arg =>
arg.UnitId == _unitId && arg.PointOfCareId == _pocCinna02Id && arg.PatientNumber == patientNumber)),
Times.Once);
That(patient, Is.Not.Null);
using (Assert.EnterMultipleScope())
{
That(patient!.PatientNumber, Is.EqualTo("12345"));
That(patient.UnitId!.Value, Is.EqualTo(_unitId));
That(patient.PointOfCareId, Is.Not.Null);
};
}
/// <summary>
/// Verifies that when a patient lookup via API request is performed for a patient that does not exist
/// while the target location is already occupied by another patient, and the <c>CreatePatientWithOru</c>
/// option is enabled, the service creates a new patient in a temporal bed instead of reusing the occupied location.
/// </summary>
[Test]
public async Task
Find_Patient_By_APIRequest_Not_Exists_And_Location_Ocuped_CreatePatientWithORU_True_Created_In_Temporal_Bed()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var apiRequest = new ApiRequest
{
Type = "ORU_R01",
PatientNumber = patientNumber,
Patient = person,
Location = location,
Facility = "Philips.CIS.CVC"
};
_optionsApiSettings.Value.CreatePatientWithOru = true;
var patientService = new PatientService(
_patientRepositoryMock.Object,
_patientArchiveRepository.Object,
_observationServiceLazy,
_treatServiceLazy,
_poCMappingServiceMock.Object,
_diagnosisServiceMock.Object,
_appointmentServiceMock.Object,
_pumpServiceLazy,
_recordingAlertService.Object,
_dischargeService.Object,
_optionsApiSettings,
_listSettings,
_logger.Object,
_clientMessageServiceMock.Object,
_subscribersServiceMock.Object,
_subscriberGroupedServiceMock.Object,
_unitService.Object,
_displayservice.Object,
_pocService.Object,
_lazyAdmissionService,
_displayConfigServiceMock.Object,
_groupedServiceMock.Object,
_patientCarePlanServiceMock.Object,
_httpContextAccessorMock.Object,
_auditServiceMock.Object,
_masterListMock.Object
);
var patientLocation = new Patient
{
PatientNumber = "11111",
Person = new Person(),
UnitId = _unitId,
PointOfCareId = _pocCinna02Id
};
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
_patientRepositoryMock.Setup(f => f.FindByLocation(location)).ReturnsAsync(patientLocation);
_patientRepositoryMock.Setup(f => f.FindByUnitAndPocId(_unitId, _pocCinna02Id)).ReturnsAsync(patientLocation);
var patient = await patientService.FindPatientByApiRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.InsertOneAsync(It.Is<Patient>(arg =>
arg.UnitId == _unitId && arg.PointOfCareId == _pocUnknowndId && arg.PatientNumber == patientNumber)),
Times.Once);
That(patient, Is.Not.Null);
using (Assert.EnterMultipleScope())
{
That(patient!.PatientNumber, Is.EqualTo("12345"));
That(patient.UnitId!.Value, Is.EqualTo(_unitId));
That(patient.PointOfCareId, Is.Not.Null);
};
}
/// <summary>
/// Verifies that when <see cref="ApiRequest.Type"/> is <c>ORU_R01</c> and the patient is not found,
/// the <see cref="Patient"/> is not created in the temporal bed because <c>CreatePatientWithOru</c> is set to <c>false</c>.
/// Ensures that <c>FindPatientByApiRequest</c> returns <c>null</c> and that the repository's <c>InsertOneAsync</c> is never invoked.
/// </summary>
[Test]
public async Task Find_Patient_By_APIRequest_Not_Exists_CreatePatientWithORU_False_Not_Created_In_Temporal_Bed()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var apiRequest = new ApiRequest
{
Type = "ORU_R01",
PatientNumber = patientNumber,
Patient = person,
Location = location,
Facility = "Philips.CIS.CVC"
};
_optionsApiSettings.Value.CreatePatientWithOru = false;
var patientService = new PatientService(
_patientRepositoryMock.Object,
_patientArchiveRepository.Object,
_observationServiceLazy,
_treatServiceLazy,
_poCMappingServiceMock.Object,
_diagnosisServiceMock.Object,
_appointmentServiceMock.Object,
_pumpServiceLazy,
_recordingAlertService.Object,
_dischargeService.Object,
_optionsApiSettings,
_listSettings,
_logger.Object,
_clientMessageServiceMock.Object,
_subscribersServiceMock.Object,
_subscriberGroupedServiceMock.Object,
_unitService.Object,
_displayservice.Object,
_pocService.Object,
_lazyAdmissionService,
_displayConfigServiceMock.Object,
_groupedServiceMock.Object,
_patientCarePlanServiceMock.Object,
_httpContextAccessorMock.Object,
_auditServiceMock.Object,
_masterListMock.Object
);
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
var patient = await patientService.FindPatientByApiRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.InsertOneAsync(It.Is<Patient>(arg =>
arg.UnitId == _unitId && arg.PointOfCareId == _pocUnknowndId && arg.PatientNumber == patientNumber)),
Times.Never);
That(patient, Is.Null);
}
/// <summary>
/// Verifies that when a patient is found by API request and the patient already exists in a different location in the database, the patient's location is not changed by the lookup operation.
/// </summary>
[Test]
public async Task Find_Patient_By_APIRequest_Exists_In_Different_Location_NOT_Changes_Patient_Location()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var apiRequest = new ApiRequest
{
Type = "ORU_R01",
PatientNumber = patientNumber,
Patient = person,
Location = location,
Facility = "Philips.CIS.CVC"
};
var patientInBd = new Patient
{
UnitId = _unitId,
PointOfCareId = _pocCinna02Id,
PatientNumber = patientNumber,
Person = new Person
{
FirstName = "Miguel",
LastName = "Villanueva",
BirthDate = new DateTime(),
Gender = PatientEnum.Gender.Male
}
};
_patientRepositoryMock.Setup(p => p.FindByPatientNumber(patientNumber)).ReturnsAsync(patientInBd);
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
var patient = await _patientService.FindPatientByApiRequest(apiRequest);
That(patient, Is.Not.Null);
using (Assert.EnterMultipleScope())
{
That(patient!.PatientNumber, Is.EqualTo("12345"));
That(patient.UnitId!.Value, Is.EqualTo(_unitId));
That(patient.PointOfCareId!.Value, Is.EqualTo((ObjectId?)_pocCinna02Id));
};
}
/// <summary>
/// Verifies that an ADT_A01 request correctly inserts a new patient into the specified unit and bed location
/// by ensuring the patient repository is updated with the matching unit, bed, and patient number.
/// </summary>
[Test]
public async Task ADT_A01_New_Patient_Empty_Bed_Insert_In_Location()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var apiRequest = new ApiRequest
{
Type = "ADT_A01",
PatientNumber = patientNumber,
Patient = person,
Location = location
};
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.Update(It.Is<Patient>(arg =>
arg.UnitString == "UCI5C" && arg.Bed == "CINA02" && arg.PatientNumber == patientNumber)),
Times.Once);
}
/// <summary>
/// Verifies that when an ADT_A01 request for a new patient is processed with an unknown location
/// (i.e., the location mapping resolves to null), the patient is not inserted into the repository.
/// </summary>
[Test]
public async Task ADT_A01_New_Patient_Unknown_Location_Insert_Nothing()
{
var location = new PatientLocation("UCI5H", "CINA02");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var apiRequest = new ApiRequest
{
Type = "ADT_A01",
PatientNumber = patientNumber,
Patient = person,
Location = location
};
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(() => null);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.InsertOneAsync(It.IsAny<Patient>()),
Times.Never);
}
/// <summary>
/// Verifies that when an ADT_A01 admission request is received for a new patient targeting a bed that is already in use by an existing patient, the existing patient is moved to the temporal (pushed) bed while the new patient is admitted to the original bed.
/// </summary>
[Test]
public async Task ADT_A01_New_Patient_Bed_In_Use_Moves_Existing_Patient_To_Temporal_Bed()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "123456";
var unitId = ObjectId.GenerateNewId();
var pocId = ObjectId.GenerateNewId();
var person = new Person
{
FirstName = "Miguel",
LastName = "Villanueva",
BirthDate = new DateTime(),
Gender = PatientEnum.Gender.Male,
Ids = new Dictionary<string, string>
{
{ "MR", "12345" },
{ "VN", "" }
}
};
var poc = new PointOfCare
{
Id = pocId,
UnitId = unitId,
Room = "CINA02",
Bed = "CINA02",
Status = StatusEnum.PointOfCare.InUse
};
var pocPushed = new PointOfCare
{
Id = ObjectId.GenerateNewId(),
UnitId = unitId,
Room = VirtualPointOfCare.Pushed.ToString(),
Bed = VirtualPointOfCare.Pushed.ToString()
};
var unit = new Unit
{
Id = unitId,
Name = "UCI5C",
Title = "CONTROLC",
Configuration = new UnitConfiguration
{
AutoAdt = true
}
};
var apiRequest = new ApiRequest
{
Type = "ADT_A01",
PatientNumber = patientNumber,
Patient = person,
Location = location
};
var mongoId = ObjectId.GenerateNewId();
var patientInBd = new Patient
{
Id = mongoId,
PointOfCareId = pocId,
UnitId = unitId,
PatientNumber = "123456",
Person = new Person
{
FirstName = "Jose",
LastName = "Luis",
BirthDate = new DateTime(),
Gender = PatientEnum.Gender.Male,
Ids = new Dictionary<string, string>
{
{ "MR", "123456" },
{ "VN", "" }
}
}
};
var existingPatient = new Patient
{
Id = ObjectId.GenerateNewId(),
PointOfCareId = pocId,
UnitId = unitId,
PatientNumber = "1234567",
Person = new Person
{
FirstName = "Jose",
LastName = "Luis",
BirthDate = new DateTime(),
Gender = PatientEnum.Gender.Male,
Ids = new Dictionary<string, string>
{
{ "MR", "123456" },
{ "VN", "" }
}
}
};
var admissionServiceMock = new Mock<IAdmissionService>();
admissionServiceMock.Setup(a => a.GetAdmissionByPatientNumber(patientNumber)).ReturnsAsync((Admission?)null);
_pocService.Setup(p => p.FindByBedAndUnitId("CINA02", It.IsAny<ObjectId>())).ReturnsAsync(poc);
_pocService.Setup(p => p.FindByBedAndUnitId(VirtualPointOfCare.Pushed.ToString(), unit.Id))
.ReturnsAsync(pocPushed);
_pocService.Setup(p => p.FindById(pocPushed.Id)).ReturnsAsync(pocPushed);
_pocService.Setup(p => p.FindById(pocId)).ReturnsAsync(poc);
_unitService.Setup(u => u.FindByName(unit.Name)).ReturnsAsync(unit);
_unitService.Setup(u => u.FindById(unit.Id)).ReturnsAsync(unit);
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
_patientRepositoryMock.Setup(p => p.FindByUnitAndPocId(unit.Id, poc.Id)).ReturnsAsync(existingPatient);
_patientRepositoryMock.Setup(p => p.FindById(existingPatient.Id)).ReturnsAsync(existingPatient);
_patientRepositoryMock.Setup(p => p.FindById(patientInBd.Id)).ReturnsAsync(patientInBd);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.FindByPatientNumber(It.Is<string>(arg => arg == patientInBd.PatientNumber)), Times.Once);
_patientRepositoryMock.Verify(
p => p.Update(It.Is<Patient>(arg =>
arg.Bed == "CINA02" && arg.PatientNumber == patientNumber)),
Times.Once);
}
/// <summary>
/// Verifies that when an ADT_A01 (Admit) message is received for a patient whose bed is already in use and whose patient number matches an existing patient, the patient's demographic data is updated while preserving the bed assignment and existing identifiers.
/// </summary>
[Test]
public async Task ADT_A01_New_Patient_Bed_In_Use_With_Same_Patient_Number_Updates_Demographic_Data()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var unitId = ObjectId.GenerateNewId();
var pocId = ObjectId.GenerateNewId();
var person = new Person
{
FirstName = "Miguel",
LastName = "Villanueva",
BirthDate = new DateTime(),
Gender = PatientEnum.Gender.Male,
Ids = new Dictionary<string, string>
{
{ "MR", patientNumber },
{ "VN", "" }
}
};
var apiRequest = new ApiRequest
{
Type = "ADT_A01",
PatientNumber = patientNumber,
Patient = person,
Location = location
};
var mongoId = ObjectId.GenerateNewId();
var patientInBd = new Patient
{
Id = mongoId,
PointOfCareId = pocId,
UnitId = unitId,
PatientNumber = patientNumber,
Person = new Person
{
FirstName = "_",
LastName = "_",
BirthDate = new DateTime(),
Gender = PatientEnum.Gender.Male,
Ids = new Dictionary<string, string>
{
{ "MR", patientNumber },
{ "VN", "" }
}
}
};
_poCMappingServiceMock.Setup(p => p.Map(location)).ReturnsAsync(location);
_patientRepositoryMock.Setup(p => p.FindById(patientInBd.Id)).ReturnsAsync(patientInBd);
_patientRepositoryMock.Setup(p => p.FindByPatientNumber(patientNumber)).ReturnsAsync(patientInBd);
_patientRepositoryMock.Setup(p => p.FindByUnitAndPocId(unitId, pocId)).ReturnsAsync(patientInBd);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.Update(It.Is<Patient>(arg =>
arg.Bed == "CINA02" && arg.PatientNumber == patientNumber && arg.Person != null &&
arg.Person.Equals(person))),
Times.Once);
}
/// <summary>
/// Verifies that processing an ADT_A05 message for a new patient in a new bed (PatientLocation) results in the patient being updated with the correct unit, point of care, and patient number, and that the point-of-care mapping service is invoked to create the location.
/// </summary>
[Test]
public async Task ADT_A05_New_Patient_New_Bed_Creates_Location()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var apiRequest = new ApiRequest
{
Type = "ADT_A01",
PatientNumber = patientNumber,
Patient = person,
Location = location
};
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.Update(It.Is<Patient>(arg =>
arg.UnitId == _unitId && arg.PointOfCareId == _pocCinna02Id && arg.PatientNumber == patientNumber)),
Times.Once);
}
/// <summary>
/// Verifies that when a new patient admission is processed for a bed that is already occupied,
/// the existing patient in that bed is moved to a temporal PointOfCare, while the new patient
/// is assigned to the original PointOfCare location.
/// </summary>
[Test]
public async Task ADT_A05_New_Patient_Bed_In_Use_Moves_Existing_Patient_To_Temporal_Bed()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var apiRequest = new ApiRequest
{
Type = "ADT_A01",
PatientNumber = patientNumber,
Patient = person,
Location = location
};
var mongoId = ObjectId.GenerateNewId();
var patientInBd = new Patient
{
Id = mongoId,
UnitId = _unitId,
PointOfCareId = _pocCinna02Id,
PatientNumber = "123456",
Person = new Person
{
FirstName = "Jose",
LastName = "Luis",
BirthDate = new DateTime(),
Gender = PatientEnum.Gender.Male
}
};
_patientRepositoryMock.Setup(p => p.FindByUnitAndPocId(_unitId, _pocCinna02Id)).ReturnsAsync(patientInBd);
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
_patientRepositoryMock.Setup(p => p.FindById(mongoId)).ReturnsAsync(patientInBd);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(p => p.UpdateOneAsync(mongoId,
It.Is<Patient>(arg => arg.UnitId == _unitId && arg.PointOfCareId == _pocPushedId)));
_patientRepositoryMock.Verify(
p => p.Update(It.Is<Patient>(arg =>
arg.UnitId == _unitId && arg.PointOfCareId == _pocCinna02Id && arg.PatientNumber == patientNumber)),
Times.Once());
}
/// <summary>
/// Verifies that when an ADT_A03 (End Visit) message is processed for a patient that does not exist,
/// the patient repository's Update operation is never invoked, ensuring the system takes no action.
/// </summary>
[Test]
public async Task ADT_A03_END_VISIT_PATIENT_NOT_EXISTS_DO_NOTHING()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var apiRequest = new ApiRequest
{
Type = "ADT_A03",
PatientNumber = patientNumber,
Patient = person,
Location = location
};
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.Update(It.Is<Patient>(arg =>
arg.PointOfCareId == _pocDeletedId && arg.UnitId == _unitId && arg.PatientNumber == patientNumber)),
Times.Never);
}
/// <summary>
/// Verifies that when an ADT_A03 (End Visit) request is processed for a patient that already exists in the database, the patient record is updated with the deleted Point of Care, the unit identifier is preserved, and the next admission check is triggered for the original Point of Care.
/// </summary>
[Test]
public async Task ADT_A03_END_VISIT_PATIENT_EXISTS()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var mongoId = ObjectId.GenerateNewId();
var apiRequest = new ApiRequest
{
Type = "ADT_A03",
PatientNumber = patientNumber,
Patient = person,
Location = location
};
var patientInBd = new Patient
{
Id = mongoId,
UnitId = _unitId,
PointOfCareId = _pocCinna02Id,
Bed = location.Bed,
PatientNumber = patientNumber,
Person = person
};
_patientRepositoryMock.Setup(p => p.FindByPatientNumber(patientNumber)).ReturnsAsync(patientInBd);
_patientRepositoryMock.Setup(p => p.FindById(mongoId)).ReturnsAsync(patientInBd);
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.UpdateOneAsync(mongoId,
It.Is<Patient>(arg =>
arg.PointOfCareId == _pocDeletedId && arg.UnitId == _unitId && arg.PatientNumber == patientNumber)),
Times.Once);
_pocService.Verify(
p => p.CheckNextAdmission(_pocCinna02Id),
Times.Once);
}
[Test]
public async Task ADT_A02_TRANSFER_PATIENT_FROM_EXISTS_BED_TO_NOT_EXISTS_BED_SHOULD_MOVE_TO_VIRTUAL_POC_UNKNOWN()
{
var location = new PatientLocation("UCI5C", "CINA02");
var otherlocation = new PatientLocation("UCI5X", "CINA01");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var apiRequest = new ApiRequest
{
Type = "ADT_A02",
PatientNumber = patientNumber,
Patient = person,
OldLocation = location,
Location = otherlocation
};
var existingPatient = new Patient
{
Id = ObjectId.GenerateNewId(),
PatientNumber = "12345",
Person = person,
Location = location,
UnitId = _unitId,
PointOfCareId = _pocCinna02Id
};
// Crear una nueva instancia de ApiSettings
var testApiSettings = new ApiSettings
{
IccaFacility = "Philips.CIS.CVC",
PointOfCareMapping = new PointOfCareMapping { Required = false }
};
// Crear una nueva instancia de IOptions<ApiSettings>
var testOptionsApiSettings = Options.Create(testApiSettings);
// Crear una nueva instancia de PatientService utilizando la configuración custom
var patientServiceForThisTest = new PatientService(
_patientRepositoryMock.Object,
_patientArchiveRepository.Object,
_observationServiceLazy,
_treatServiceLazy,
_poCMappingServiceMock.Object,
_diagnosisServiceMock.Object,
_appointmentServiceMock.Object,
_pumpServiceLazy,
_recordingAlertService.Object,
_dischargeService.Object,
testOptionsApiSettings,
_listSettings,
_logger.Object,
_clientMessageServiceMock.Object,
_subscribersServiceMock.Object,
_subscriberGroupedServiceMock.Object,
_unitService.Object,
_displayservice.Object,
_pocService.Object,
_lazyAdmissionService,
_displayConfigServiceMock.Object,
_groupedServiceMock.Object,
_patientCarePlanServiceMock.Object,
_httpContextAccessorMock.Object,
_auditServiceMock.Object,
_masterListMock.Object
);
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
_poCMappingServiceMock.Setup(i => i.Map(otherlocation)).ReturnsAsync(otherlocation);
_patientRepositoryMock.Setup(i => i.FindByPatientNumber(patientNumber)).ReturnsAsync(existingPatient);
_patientRepositoryMock.Setup(i => i.FindById(existingPatient.Id)).ReturnsAsync(existingPatient);
await patientServiceForThisTest.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.UpdateOneAsync(existingPatient.Id,
It.Is<Patient>(x => x.PointOfCareId == _pocUnknowndId && x.PatientNumber == patientNumber)),
Times.Once());
}
/// <summary>
/// Verifies that when an ADT_A02 transfer request is received for a patient that does not yet exist
/// in the system, the patient service creates a new patient record in the destination bed.
/// Mocks the patient repository to return null for the lookup by patient number and the PoC mapping
/// service to resolve the destination location, ensuring the save operation results in a single
/// insert for the new patient.
/// </summary>
[Test]
public async Task ADT_A02_TRANSFER_PATIENT_FROM_NOT_EXISTS_BED_TO_BED_SHOULD_CREATE_PATIENT()
{
var location = new PatientLocation("UCI5C", "CINA02", "CINA02");
var oldLocation = new PatientLocation("UCI5C", "CINA04", "CINA04");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var mongoId = ObjectId.GenerateNewId();
var apiRequest = new ApiRequest
{
Type = "ADT_A02",
PatientNumber = patientNumber,
Patient = person,
Location = location,
OldLocation = oldLocation
};
var newPatientInBed = new Patient
{
UnitId = _unitId,
PointOfCareId = _pocCinna02Id,
PatientNumber = patientNumber,
Person = person,
Location = location
};
_patientRepositoryMock.Setup(p => p.FindByPatientNumber(patientNumber)).ReturnsAsync((Patient?)null);
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
_patientRepositoryMock.Setup(p => p.FindById(mongoId)).ReturnsAsync((Patient?)null);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.InsertOneAsync(It.Is<Patient>(arg => arg.PatientNumber == newPatientInBed.PatientNumber)),
Times.Once);
}
/// <summary>
/// Tests the ADT_A02 transfer scenario where a patient is transferred from their current bed to a bed that is already occupied by another patient, verifying that the existing patient is moved to a new location, the transferring patient occupies the destination bed, and related discharge and next-admission checks are invoked.
/// </summary>
[Test]
public async Task ADT_A02_TRANSFER_PATIENT_FROM_BED_TO_IN_USE_BED()
{
// Old Location for existing patient
var oldLocation = new PatientLocation("UCI5C", "CINA03");
// New Location for existing patient
var location = new PatientLocation("UCI5C", "CINA02");
const string newPatientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var mongoIdNewPatient = ObjectId.GenerateNewId();
// Existing patient in new patient location
var mongoIdOldPatient = ObjectId.GenerateNewId();
var oldPatientInBed = new Patient
{
Id = mongoIdOldPatient,
UnitId = _unitId,
PointOfCareId = _pocCinna02Id,
PatientNumber = "123456",
Person = new Person
{
FirstName = "Jose",
LastName = "Luis",
BirthDate = new DateTime(),
Gender = PatientEnum.Gender.Male
}
};
var newPatientInBed = new Patient
{
Id = mongoIdNewPatient,
PointOfCareId = _pocCinna03Id,
UnitId = _unitId,
PatientNumber = newPatientNumber,
Person = person
};
var apiRequest = new ApiRequest
{
Type = "ADT_A02",
PatientNumber = newPatientNumber,
Patient = person,
Location = location,
OldLocation = oldLocation
};
_patientRepositoryMock.Setup(p => p.FindByPatientNumber(newPatientNumber)).ReturnsAsync(newPatientInBed);
_patientRepositoryMock.Setup(p => p.FindByLocation(location)).ReturnsAsync(oldPatientInBed);
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
_patientRepositoryMock.Setup(p => p.FindByUnitAndPocId(_unitId, _pocCinna02Id)).ReturnsAsync(oldPatientInBed);
_patientRepositoryMock.Setup(p => p.FindById(oldPatientInBed.Id)).ReturnsAsync(oldPatientInBed);
_patientRepositoryMock.Setup(p => p.FindById(newPatientInBed.Id)).ReturnsAsync(newPatientInBed);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.UpdateOneAsync(mongoIdOldPatient,
It.Is<Patient>(arg => arg.UnitId == _unitId && arg.PointOfCareId == _pocMovedId)), Times.Once());
_dischargeService.Verify(p => p.GetDischargeByPatientId(mongoIdOldPatient), Times.Once);
_patientRepositoryMock.Verify(
p => p.UpdateOneAsync(mongoIdNewPatient,
It.Is<Patient>(arg => arg.UnitId == _unitId && arg.PointOfCareId == _pocCinna02Id)), Times.Once());
_pocService.Verify(p => p.CheckNextAdmission(_pocMovedId), Times.Once);
}
/// <summary>
/// Verifies that when an ADT_A02 transfer message is processed for a patient moving from a location with no existing patient to a bed that is already occupied, the previously assigned patient is moved to a temporal bed and the new patient is inserted into the vacated bed.
/// </summary>
[Test]
public async Task
ADT_A02_TRANSFER_PATIENT_FROM_NOT_EXISTS_TO_NOT_EMPTY_BED_SHOULD_CHANGE_LAST_PATIENT_TO_TEMPORTAL_BED()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var mongoId = ObjectId.GenerateNewId();
var apiRequest = new ApiRequest
{
Type = "ADT_A02",
PatientNumber = patientNumber,
Patient = person,
Location = location
};
var oldPatientInBed = new Patient
{
Id = mongoId,
UnitId = _unitId,
PointOfCareId = _pocCinna02Id,
PatientNumber = "123456",
Person = new Person
{
FirstName = "Jose",
LastName = "Luis",
BirthDate = new DateTime(),
Gender = PatientEnum.Gender.Male
}
};
_patientRepositoryMock.Setup(p => p.FindByUnitAndPocId(_unitId, _pocCinna02Id)).ReturnsAsync(oldPatientInBed);
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
_patientRepositoryMock.Setup(p => p.FindById(mongoId)).ReturnsAsync(oldPatientInBed);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.UpdateOneAsync(mongoId,
It.Is<Patient>(arg =>
arg.UnitId == _unitId && arg.PointOfCareId == _pocMovedId &&
arg.PatientNumber == oldPatientInBed.PatientNumber)), Times.Once);
_patientRepositoryMock.Verify(
p => p.InsertOneAsync(It.Is<Patient>(arg =>
arg.UnitId == _unitId && arg.PointOfCareId == _pocCinna02Id && arg.PatientNumber == patientNumber)),
Times.Once());
}
/// <summary>
/// Verifies that processing an ADT_A02 transfer request for a patient whose patient number already exists in the destination bed updates the existing patient's demographic data instead of creating a new patient record.
/// </summary>
[Test]
public async Task
ADT_A02_TRANSFER_PATIENT_FROM_NOT_EXISTS_BED_TO_NOT_EMPTY_BED_WITH_SAME_PATIENT_NUMBER_SHOULD_UPTADE_DEMOGRAPHIC_DATA()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var mongoId = ObjectId.GenerateNewId();
var apiRequest = new ApiRequest
{
Type = "ADT_A02",
PatientNumber = patientNumber,
Patient = person,
Location = location
};
var oldPatientInBed = new Patient
{
Id = mongoId,
UnitId = _unitId,
PointOfCareId = _pocCinna02Id,
PatientNumber = patientNumber,
Person = new Person
{
FirstName = "_",
LastName = "_"
}
};
_patientRepositoryMock.Setup(p => p.FindByUnitAndPocId(_unitId, _pocCinna02Id)).ReturnsAsync(oldPatientInBed);
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
_patientRepositoryMock.Setup(p => p.FindByPatientNumber(patientNumber)).ReturnsAsync(oldPatientInBed);
_patientRepositoryMock.Setup(p => p.FindById(mongoId)).ReturnsAsync(oldPatientInBed);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.UpdatePatientData(mongoId, patientNumber, It.Is<Person>(arg => arg.Equals(person)), false),
Times.Once);
_patientRepositoryMock.Verify(
p => p.InsertOneAsync(It.IsAny<Patient>()),
Times.Never);
}
/// <summary>
/// Verifies that processing an ADT_A04 message for a new patient successfully creates and persists a patient record with the expected unit, point of care, and patient number.
/// </summary>
[Test]
public async Task ADT_A04_New_Patient_Creates_Patient()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var apiRequest = new ApiRequest
{
Type = "ADT_A04",
PatientNumber = patientNumber,
Patient = person,
Location = location
};
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.InsertOneAsync(It.Is<Patient>(arg =>
arg.UnitId == _unitId && arg.PointOfCareId == _pocCinna02Id && arg.PatientNumber == patientNumber)),
Times.Once);
}
/// <summary>
/// Verifies that when processing an ADT_A04 request for a new patient with a location whose POC mapping returns null, the patient is not persisted to the repository.
/// </summary>
[Test]
public async Task ADT_A04_New_Patient_Not_Location_Creates_Patient()
{
var location = new PatientLocation("NEONATAL", "CINA02");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var apiRequest = new ApiRequest
{
Type = "ADT_A04",
PatientNumber = patientNumber,
Patient = person,
Location = location
};
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync((PatientLocation?)null);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.InsertOneAsync(It.Is<Patient>(arg => arg.PatientNumber == patientNumber)), Times.Never);
}
/// <summary>
/// Verifies that when an ADT_A08 request is received for a non-existent patient and the <c>CreatePatientWithAdtA08</c> option is enabled, the <see cref="PatientService"/> correctly creates the patient by calling the patient repository's <c>Update</c> method with the expected <c>UnitId</c>, <c>PointOfCareId</c>, and <c>PatientNumber</c> values.
/// </summary>
[Test]
public async Task ADT_A08_No_exist_CreatePatientWithADT_A08_True_Patient_Creates_Patient()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var apiRequest = new ApiRequest
{
Type = "ADT_A08",
PatientNumber = patientNumber,
Patient = person,
Location = location
};
_optionsApiSettings.Value.CreatePatientWithAdtA08 = true;
var patientService = new PatientService(
_patientRepositoryMock.Object,
_patientArchiveRepository.Object,
_observationServiceLazy,
_treatServiceLazy,
_poCMappingServiceMock.Object,
_diagnosisServiceMock.Object,
_appointmentServiceMock.Object,
_pumpServiceLazy,
_recordingAlertService.Object,
_dischargeService.Object,
_optionsApiSettings,
_listSettings,
_logger.Object,
_clientMessageServiceMock.Object,
_subscribersServiceMock.Object,
_subscriberGroupedServiceMock.Object,
_unitService.Object,
_displayservice.Object,
_pocService.Object,
_lazyAdmissionService,
_displayConfigServiceMock.Object,
_groupedServiceMock.Object,
_patientCarePlanServiceMock.Object,
_httpContextAccessorMock.Object,
_auditServiceMock.Object,
_masterListMock.Object
);
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
// Act
await patientService.SaveRequest(apiRequest);
// Assert: Verify that the Update method is called with the correct patient
_patientRepositoryMock.Verify(p => p.Update(It.Is<Patient>(arg =>
arg.UnitId == _unitId &&
arg.PointOfCareId == _pocCinna02Id &&
arg.PatientNumber == patientNumber)), Times.Once);
// Add additional logging for debugging
Console.WriteLine("Test completed successfully");
}
/// <summary>
/// Verifies that when an ADT_A08 message is processed for a patient that does not exist and the
/// <c>CreatePatientWithAdtA08</c> option is disabled, the patient is not inserted into the repository.
/// </summary>
[Test]
public async Task ADT_A08_No_exist_Patient_Not_Creates_Patient()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var apiRequest = new ApiRequest
{
Type = "ADT_A08",
PatientNumber = patientNumber,
Patient = person,
Location = location
};
_optionsApiSettings.Value.CreatePatientWithAdtA08 = false;
var patientService = new PatientService(
_patientRepositoryMock.Object,
_patientArchiveRepository.Object,
_observationServiceLazy,
_treatServiceLazy,
_poCMappingServiceMock.Object,
_diagnosisServiceMock.Object,
_appointmentServiceMock.Object,
_pumpServiceLazy,
_recordingAlertService.Object,
_dischargeService.Object,
_optionsApiSettings,
_listSettings,
_logger.Object,
_clientMessageServiceMock.Object,
_subscribersServiceMock.Object,
_subscriberGroupedServiceMock.Object,
_unitService.Object,
_displayservice.Object,
_pocService.Object,
_lazyAdmissionService,
_displayConfigServiceMock.Object,
_groupedServiceMock.Object,
_patientCarePlanServiceMock.Object,
_httpContextAccessorMock.Object,
_auditServiceMock.Object,
_masterListMock.Object
);
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
await patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.InsertOneAsync(It.Is<Patient>(arg =>
arg.UnitId == _unitId &&
arg.PointOfCareId == _pocCinna02Id
&& arg.PatientNumber == patientNumber)),
Times.Never);
}
/// <summary>
/// Verifies that when an existing patient is processed via an ADT_A08 (Patient Update) message
/// and patient creation on ADT_A08 is disabled, the patient is updated rather than created.
/// </summary>
/// <returns>A task that represents the asynchronous test execution.</returns>
[Test]
public async Task ADT_A08_Exist_Patient_Update_Patient()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var apiRequest = new ApiRequest
{
Type = "ADT_A08",
PatientNumber = patientNumber,
Patient = person,
Location = location
};
var patient = new Patient
{
UnitId = _unitId,
PointOfCareId = _pocCinna02Id,
PatientNumber = patientNumber,
Person = person
};
_optionsApiSettings.Value.CreatePatientWithAdtA08 = false;
var patientService = new PatientService(
_patientRepositoryMock.Object,
_patientArchiveRepository.Object,
_observationServiceLazy,
_treatServiceLazy,
_poCMappingServiceMock.Object,
_diagnosisServiceMock.Object,
_appointmentServiceMock.Object,
_pumpServiceLazy,
_recordingAlertService.Object,
_dischargeService.Object,
_optionsApiSettings,
_listSettings,
_logger.Object,
_clientMessageServiceMock.Object,
_subscribersServiceMock.Object,
_subscriberGroupedServiceMock.Object,
_unitService.Object,
_displayservice.Object,
_pocService.Object,
_lazyAdmissionService,
_displayConfigServiceMock.Object,
_groupedServiceMock.Object,
_patientCarePlanServiceMock.Object,
_httpContextAccessorMock.Object,
_auditServiceMock.Object,
_masterListMock.Object
);
_patientRepositoryMock.Setup(f => f.FindByPatientNumber(patientNumber)).ReturnsAsync(patient);
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
await patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.Update(It.Is<Patient>(arg =>
arg.UnitId == _unitId && arg.PointOfCareId == _pocCinna02Id && arg.PatientNumber == patientNumber)),
Times.Once);
}
/// <summary>
/// Verifies that processing an ADT_A11 (cancel admit/visit notification) message for an existing patient updates the patient's location to the cancelled point of care, leaving unit, patient number, and identity fields unchanged.
/// </summary>
[Test]
public async Task ADT_A11_Exist_Patient_CANCELLED_Patient()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var apiRequest = new ApiRequest
{
Type = "ADT_A11",
PatientNumber = patientNumber,
Patient = person,
Location = location
};
var patient = new Patient
{
UnitId = _unitId,
PointOfCareId = _pocCinna02Id,
PatientNumber = patientNumber,
Person = person,
Id = ObjectId.GenerateNewId()
};
var patientService = new PatientService(
_patientRepositoryMock.Object,
_patientArchiveRepository.Object,
_observationServiceLazy,
_treatServiceLazy,
_poCMappingServiceMock.Object,
_diagnosisServiceMock.Object,
_appointmentServiceMock.Object,
_pumpServiceLazy,
_recordingAlertService.Object,
_dischargeService.Object,
_optionsApiSettings,
_listSettings,
_logger.Object,
_clientMessageServiceMock.Object,
_subscribersServiceMock.Object,
_subscriberGroupedServiceMock.Object,
_unitService.Object,
_displayservice.Object,
_pocService.Object,
_lazyAdmissionService,
_displayConfigServiceMock.Object,
_groupedServiceMock.Object,
_patientCarePlanServiceMock.Object,
_httpContextAccessorMock.Object,
_auditServiceMock.Object,
_masterListMock.Object
);
_patientRepositoryMock.Setup(f => f.FindByPatientNumber(patientNumber)).ReturnsAsync(patient);
// sectionServiceMock.Setup(f => f.FindByPatient(patient.id)).ReturnsAsync(null);
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
await patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.UpdateOneAsync(patient.Id,
It.Is<Patient>(arg =>
arg.UnitId == _unitId && arg.PointOfCareId == _pocCanceledId &&
arg.PatientNumber == patientNumber)),
Times.Once);
}
/// <summary>
/// Verifies that when an ADT_A11 (cancel admit/visit notification) request is processed for a non-existent patient, the patient repository's <c>UpdateOneAsync</c> method is never invoked, since there is no existing patient record to update.
/// </summary>
[Test]
public async Task ADT_A11_No_Exist_Patient_Not_CANCELLED_Patient()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var apiRequest = new ApiRequest
{
Type = "ADT_A11",
PatientNumber = patientNumber,
Patient = person,
Location = location
};
var patientService = new PatientService(
_patientRepositoryMock.Object,
_patientArchiveRepository.Object,
_observationServiceLazy,
_treatServiceLazy,
_poCMappingServiceMock.Object,
_diagnosisServiceMock.Object,
_appointmentServiceMock.Object,
_pumpServiceLazy,
_recordingAlertService.Object,
_dischargeService.Object,
_optionsApiSettings,
_listSettings,
_logger.Object,
_clientMessageServiceMock.Object,
_subscribersServiceMock.Object,
_subscriberGroupedServiceMock.Object,
_unitService.Object,
_displayservice.Object,
_pocService.Object,
_lazyAdmissionService,
_displayConfigServiceMock.Object,
_groupedServiceMock.Object,
_patientCarePlanServiceMock.Object,
_httpContextAccessorMock.Object,
_auditServiceMock.Object,
_masterListMock.Object
);
await patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.UpdateOneAsync(It.IsAny<ObjectId>(),
It.Is<Patient>(arg =>
arg.UnitId == _unitId && arg.PointOfCareId == _pocCanceledId &&
arg.PatientNumber == patientNumber)),
Times.Never);
}
/// <summary>
/// Verifies that processing an ADT_A12 transfer message for a non-existing patient to an empty bed
/// results in the patient being created and assigned to the target bed via the point-of-care mapping.
/// </summary>
[Test]
public async Task ADT_A12_TRANSFER_PATIENT_NOT_EXISTS_TO_EMPTY_BED_SHOULD_CREATE_BED()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var apiRequest = new ApiRequest
{
Type = "ADT_A12",
PatientNumber = patientNumber,
Patient = person,
Location = location
};
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.InsertOneAsync(It.Is<Patient>(arg =>
arg.UnitId == _unitId && arg.PointOfCareId == _pocCinna02Id && arg.PatientNumber == patientNumber)),
Times.Once());
}
/// <summary>
/// Verifies that when an ADT_A12 transfer request targets a bed that does not exist, the service
/// creates the bed (represented by a new point of care) and persists the patient's transfer to that
/// new location under the configured unit.
/// </summary>
[Test]
public async Task ADT_A12_TRANSFER_PATIENT_FROM_BED_TO_NOT_EXISTS_BED_SHOULD_CREATE_BED()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var mongoId = ObjectId.GenerateNewId();
var apiRequest = new ApiRequest
{
Type = "ADT_A12",
PatientNumber = patientNumber,
Patient = person,
Location = location
};
var newPatientInBed = new Patient
{
Id = mongoId,
UnitId = _unitId,
PointOfCareId = ObjectId.GenerateNewId(),
PatientNumber = patientNumber,
Person = person
};
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
_patientRepositoryMock.Setup(p => p.FindByPatientNumber(patientNumber)).ReturnsAsync(newPatientInBed);
_patientRepositoryMock.Setup(p => p.FindById(mongoId)).ReturnsAsync(newPatientInBed);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.UpdateOneAsync(mongoId,
It.Is<Patient>(arg => arg.UnitId == _unitId && arg.PointOfCareId == _pocCinna02Id)), Times.Once);
}
/// <summary>
/// Verifies that when an ADT_A12 transfer request is processed, the new patient occupying the target bed has their data updated while the displaced patient is relocated to a different point of care, and that the legacy <c>Update</c> method is not invoked.
/// </summary>
[Test]
public async Task ADT_A12_TRANSFER_PATIENT_FROM_BED_TO_IN_USE_BED()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var mongoIdOldPatient = ObjectId.GenerateNewId();
var mongoIdNewPatient = ObjectId.GenerateNewId();
var apiRequest = new ApiRequest
{
Type = "ADT_A12",
PatientNumber = patientNumber,
Patient = person,
Location = location
};
var oldPatientInBed = new Patient
{
Id = mongoIdOldPatient,
UnitId = _unitId,
PointOfCareId = _pocCinna02Id,
PatientNumber = "123456",
Person = new Person
{
FirstName = "Jose",
LastName = "Luis",
BirthDate = new DateTime(),
Gender = PatientEnum.Gender.Male
}
};
var newPatientInBed = new Patient
{
Id = mongoIdNewPatient,
UnitId = _unitId,
PointOfCareId = _pocCinna03Id,
PatientNumber = patientNumber,
Person = person
};
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
_patientRepositoryMock.Setup(p => p.FindByUnitAndPocId(_unitId, _pocCinna02Id)).ReturnsAsync(oldPatientInBed);
_patientRepositoryMock.Setup(p => p.FindByPatientNumber(patientNumber)).ReturnsAsync(newPatientInBed);
_patientRepositoryMock.Setup(p => p.FindById(It.Is<ObjectId>(id => id == mongoIdOldPatient)))
.ReturnsAsync(oldPatientInBed);
_patientRepositoryMock.Setup(p => p.FindById(It.Is<ObjectId>(id => id == mongoIdNewPatient)))
.ReturnsAsync(newPatientInBed);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.UpdatePatientData(mongoIdNewPatient, patientNumber, It.Is<Person>(arg => arg.Equals(person)), false),
Times.Once);
_patientRepositoryMock.Verify(
p => p.UpdateOneAsync(mongoIdOldPatient,
It.Is<Patient>(arg => arg.UnitId == _unitId && arg.PointOfCareId == _pocMovedId)), Times.Once);
_patientRepositoryMock.Verify(p => p.Update(It.IsAny<Patient>()), Times.Never());
}
/// <summary>
/// Verifies that when an ADT_A12 transfer is processed for a patient moving to a bed that is already occupied, the existing patient in that bed is moved to a temporary bed (different Point of Care), and the transferred patient is inserted into the target bed.
/// </summary>
[Test]
public async Task
ADT_A12_TRANSFER_PATIENT_NOT_EXISTS_TO_NOT_EMPTY_BED_SHOULD_CHANGE_LAST_PATIENT_TO_TEMPORTAL_BED()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var mongoId = ObjectId.GenerateNewId();
var apiRequest = new ApiRequest
{
Type = "ADT_A12",
PatientNumber = patientNumber,
Patient = person,
Location = location
};
var oldPatientInBed = new Patient
{
Id = mongoId,
UnitId = _unitId,
PointOfCareId = _pocCinna02Id,
PatientNumber = "123456",
Person = new Person
{
FirstName = "Jose",
LastName = "Luis",
BirthDate = new DateTime(),
Gender = PatientEnum.Gender.Male
}
};
_patientRepositoryMock.Setup(p => p.FindByUnitAndPocId(_unitId, _pocCinna02Id)).ReturnsAsync(oldPatientInBed);
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
_patientRepositoryMock.Setup(p => p.FindById(mongoId)).ReturnsAsync(oldPatientInBed);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.UpdateOneAsync(mongoId,
It.Is<Patient>(arg => arg.UnitId == _unitId && arg.PointOfCareId == _pocMovedId)), Times.Once);
_patientRepositoryMock.Verify(
p => p.InsertOneAsync(It.Is<Patient>(arg =>
arg.UnitId == _unitId && arg.PointOfCareId == _pocCinna02Id && arg.PatientNumber == patientNumber)),
Times.Once());
}
/// <summary>
/// Verifies that when an ADT_A13 transfer request is processed for a patient moving to a bed that is already occupied, the previously assigned patient in that bed is moved to a temporal bed while the transferring patient is persisted in the requested location.
/// </summary>
[Test]
public async Task
ADT_A13_TRANSFER_PATIENT_NOT_EXISTS_TO_NOT_EMPTY_BED_SHOULD_CHANGE_LAST_PATIENT_TO_TEMPORTAL_BED()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var mongoId = ObjectId.GenerateNewId();
var apiRequest = new ApiRequest
{
Type = "ADT_A13",
PatientNumber = patientNumber,
Patient = person,
Location = location
};
var patient = new Patient
{
Id = mongoId,
UnitId = _unitId,
PointOfCareId = _pocCinna02Id,
PatientNumber = patientNumber,
Person = person
};
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
_patientRepositoryMock.Setup(p => p.FindByPatientNumber(patientNumber)).ReturnsAsync(patient);
_patientRepositoryMock.Setup(p => p.FindById(mongoId)).ReturnsAsync(patient);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.UpdateOneAsync(mongoId,
It.Is<Patient>(arg => arg.UnitId == _unitId && arg.PointOfCareId == _pocCinna02Id)),
Times.Once);
}
/// <summary>
/// Verifies that processing an ADT_A13 transfer request for a patient assigned to a deleted point of care moves the patient to the recovered (temporal) bed location.
/// </summary>
[Test]
public async Task ADT_A13_TRANSFER_PATIENT_NOT_EXISTS_TO_EMPTY_BED_SHOULD_CHANGE_LAST_PATIENT_TO_TEMPORTAL_BED()
{
var location = new PatientLocation("UCI5C", "");
const string patientNumber = "12345";
var recoveredLocation = new PatientLocation("UCI5C", "Recovered", "Recovered");
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var mongoId = ObjectId.GenerateNewId();
var apiRequest = new ApiRequest
{
Type = "ADT_A13",
PatientNumber = patientNumber,
Patient = person,
Location = location
};
var patient = new Patient
{
Id = mongoId,
UnitId = _unitId,
PointOfCareId = _pocDeletedId,
PatientNumber = patientNumber,
Person = person
};
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
_poCMappingServiceMock
.Setup(i => i.Map(It.Is<PatientLocation>(l => l.UnitName == recoveredLocation.UnitName && l.Bed == recoveredLocation.Bed)))
.ReturnsAsync(recoveredLocation);
_patientRepositoryMock.Setup(p => p.FindByPatientNumber(patientNumber)).ReturnsAsync(patient);
_patientRepositoryMock.Setup(p => p.FindById(mongoId)).ReturnsAsync(patient);
_patientRepositoryMock.Setup(p => p.FindByUnitAndPocId(_unitId, _pocDeletedId)).ReturnsAsync(patient);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.UpdateOneAsync(mongoId, It.Is<Patient>(arg =>
arg.UnitId == _unitId &&
arg.PointOfCareId == _pocRecoveredId)),
Times.Once);
}
/// <summary>
/// Verifies that processing an ADT_A31 (Update Patient) HL7 request correctly updates the existing patient's demographic
/// information (last name and birth date) while preserving the assigned unit and point of care identifiers.
/// </summary>
[Test]
public async Task ADT_A31_Upadate_Patient()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var person = new Person { FirstName = "Miguel", LastName = "Vill", Gender = PatientEnum.Gender.Male };
var mongoId = ObjectId.GenerateNewId();
var neWperson = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var apiRequest = new ApiRequest
{
Type = "ADT_A31",
PatientNumber = patientNumber,
Patient = neWperson,
Location = location
};
var patient = new Patient
{
Id = mongoId,
UnitId = _unitId,
PointOfCareId = _pocCinna02Id,
PatientNumber = patientNumber,
Person = person
};
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
_patientRepositoryMock.Setup(p => p.FindByPatientNumber(patientNumber)).ReturnsAsync(patient);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(p => p.Update(It.Is<Patient>(arg => arg.UnitId == _unitId &&
arg.PointOfCareId == _pocCinna02Id
&& arg.Person != null &&
arg.Person.LastName == neWperson.LastName
&& arg.Person.BirthDate ==
neWperson.BirthDate)), Times.Once);
}
/// <summary>
/// Verifies that when an ADT_A31 update request is processed for a patient that does not exist, the patient is not updated. Ensures the repository's Update method is never invoked in the not-found scenario.
/// </summary>
[Test]
public async Task ADT_A31_Upadate_Patient_Not_Found_Not_Update()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
var neWperson = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var apiRequest = new ApiRequest
{
Type = "ADT_A31",
PatientNumber = patientNumber,
Patient = neWperson,
Location = location
};
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(p => p.Update(It.Is<Patient>(arg => arg.UnitId == _unitId &&
arg.PointOfCareId == _pocCinna02Id
&& arg.Person != null &&
arg.Person.LastName == neWperson.LastName
&& arg.Person.BirthDate ==
neWperson.BirthDate)), Times.Never);
}
/// <summary>
/// Verifies that when an ADT_A39 merge patient request is processed, the old patient record is deleted after the new patient is resolved through the point-of-care mapping and patient repository lookups.
/// </summary>
[Test]
public async Task ADT_A39_Merge_Patient()
{
var location = new PatientLocation("UCI5C", "CINA02");
var oldLocation = new PatientLocation("XXXXXX", "XXXXXX");
const string patientNumber = "12345";
const string oldPatientNumber = "54321";
var person = new Person { FirstName = "Miguel", LastName = "Vill", Gender = PatientEnum.Gender.Male };
var mongoId = ObjectId.GenerateNewId();
var oldPerson = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var apiRequest = new ApiRequest
{
Type = "ADT_A39",
PatientNumber = patientNumber,
OldPatientNumber = oldPatientNumber,
Location = location
};
var patient = new Patient
{
Id = mongoId,
UnitId = _unitId,
PointOfCareId = _pocCinna02Id,
PatientNumber = patientNumber,
Person = person
};
var oldPatient = new Patient
{
Id = ObjectId.GenerateNewId(),
UnitString = oldLocation.UnitName,
Bed = oldLocation.Bed,
PatientNumber = oldPatientNumber,
Person = oldPerson
};
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
_patientRepositoryMock.Setup(p => p.FindByPatientNumber(patientNumber)).ReturnsAsync(patient);
_patientRepositoryMock.Setup(p => p.FindByPatientNumber(oldPatientNumber)).ReturnsAsync(oldPatient);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(p => p.Delete(oldPatient.Id), Times.Once);
}
/// <summary>
/// Verifies that when an <c>ADT_A39</c> request is processed and the patient is not an old patient (i.e., not a merge case),
/// the <see cref="PatientService.SaveRequest"/> does not delete the existing patient from the repository.
/// </summary>
[Test]
public async Task ADT_A39_Not_OldPatient_Not_Merge_Patient()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
const string oldPatientNumber = "54321";
var person = new Person { FirstName = "Miguel", LastName = "Vill", Gender = PatientEnum.Gender.Male };
var mongoId = ObjectId.GenerateNewId();
var apiRequest = new ApiRequest
{
Type = "ADT_A39",
PatientNumber = patientNumber,
OldPatientNumber = oldPatientNumber,
Location = location
};
var patient = new Patient
{
Id = mongoId,
UnitId = _unitId,
PointOfCareId = _pocCinna02Id,
PatientNumber = patientNumber,
Person = person
};
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
_patientRepositoryMock.Setup(p => p.FindByPatientNumber(patientNumber)).ReturnsAsync(patient);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(p => p.Delete(It.IsAny<ObjectId>()), Times.Never);
}
/// <summary>
/// Verifies that processing an ADT_A39 (merge patient) request does not result in the deletion of the old patient record, even when the old patient is located by number.
/// </summary>
[Test]
public async Task ADT_A39_Not_Patient_Not_Merge_Patient()
{
var location = new PatientLocation("NEONATAL", "CINA02");
var oldLocation = new PatientLocation("XXXXXX", "XXXXXX");
const string patientNumber = "12345";
const string oldPatientNumber = "54321";
var oldPerson = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var apiRequest = new ApiRequest
{
Type = "ADT_A39",
PatientNumber = patientNumber,
OldPatientNumber = oldPatientNumber,
Location = location
};
var oldPatient = new Patient
{
Id = ObjectId.GenerateNewId(),
UnitString = oldLocation.UnitName,
Bed = oldLocation.Bed,
PatientNumber = oldPatientNumber,
Person = oldPerson
};
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
_patientRepositoryMock.Setup(p => p.FindByPatientNumber(oldPatientNumber)).ReturnsAsync(oldPatient);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(p => p.Delete(oldPatient.Id), Times.Never);
}
/// <summary>
/// Verifies that the patient service correctly handles an ADT_A44 patient merge/update request by locating the existing patient via the old patient number and updating it in the repository with the new patient information.
/// </summary>
[Test]
public async Task ADT_A44_Upadate_Patient()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
const string oldPatientNumber = "54321";
var person = new Person { FirstName = "Miguel", LastName = "Vill", Gender = PatientEnum.Gender.Male };
var newPerson = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var apiRequest = new ApiRequest
{
Type = "ADT_A44",
PatientNumber = patientNumber,
Patient = newPerson,
Location = location,
OldPatientNumber = oldPatientNumber
};
var oldPatient = new Patient
{
Id = ObjectId.GenerateNewId(),
UnitId = _unitId,
PointOfCareId = _pocCinna02Id,
Person = person
};
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
_patientRepositoryMock.Setup(p => p.FindByPatientNumber(oldPatientNumber)).ReturnsAsync(oldPatient);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(p => p.Update(It.Is<Patient>(arg => arg.PatientNumber == patientNumber)),
Times.Once);
}
/// <summary>
/// Verifies that processing an ADT_A44 request for a patient that is not an old patient does not trigger a patient update.
/// </summary>
[Test]
public async Task ADT_A44_Not_OldPatient_Not__Upadate_Patient()
{
var location = new PatientLocation("UCI5C", "CINA02");
const string patientNumber = "12345";
const string oldPatientNumber = "54321";
var newPerson = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var apiRequest = new ApiRequest
{
Type = "ADT_A44",
PatientNumber = patientNumber,
Patient = newPerson,
Location = location,
OldPatientNumber = oldPatientNumber
};
_poCMappingServiceMock.Setup(i => i.Map(location)).ReturnsAsync(location);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(p => p.Update(It.Is<Patient>(arg => arg.PatientNumber == patientNumber)),
Times.Never);
}
/// <summary>
/// Verifies that when no patients exist in the database, the ICCA processing flow inserts all provided ICCA patients
/// through the patient service by calling <c>SaveRequest</c> with an <c>ApiRequest</c> of type "ICCA" containing four
/// patients located in different points of care, and confirms each one is persisted exactly once via the repository.
/// </summary>
[Test]
public async Task ICCA_Process_No_Patient_BD_Insert_ICCA_Patients()
{
var iccaPatients = new List<PatientIcca>
{
new()
{
Location = new PatientLocation("UCI5C", "CINA01"),
PatientNumber = "patientNumber_1",
PatientId = "patientId_1",
AdmitTime = DateTime.Now
},
new()
{
Location = new PatientLocation("UCI5C", "CINA02"),
PatientNumber = "patientNumber_2",
PatientId = "patientId_2",
AdmitTime = DateTime.Now
},
new()
{
Location = new PatientLocation("UCI5C", "CINA03"),
PatientNumber = "patientNumber_3",
PatientId = "patientId_3",
AdmitTime = DateTime.Now
},
new()
{
Location = new PatientLocation("UCI5C", "CINA04"),
PatientNumber = "patientNumber_4",
PatientId = "patientId_4",
AdmitTime = DateTime.Now
}
};
var apiRequest = new ApiRequest
{
Type = "ICCA",
IccaPatients = iccaPatients
};
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.InsertOneAsync(It.Is<Patient>(arg =>
arg.UnitId == _unitId &&
arg.PointOfCareId == _pocCinna01Id && arg.PatientNumber == iccaPatients[0].PatientNumber)),
Times.Once);
_patientRepositoryMock.Verify(
p => p.InsertOneAsync(It.Is<Patient>(arg =>
arg.UnitId == _unitId &&
arg.PointOfCareId == _pocCinna02Id && arg.PatientNumber == iccaPatients[1].PatientNumber)),
Times.Once);
_patientRepositoryMock.Verify(
p => p.InsertOneAsync(It.Is<Patient>(arg =>
arg.UnitId == _unitId &&
arg.PointOfCareId == _pocCinna03Id && arg.PatientNumber == iccaPatients[2].PatientNumber)),
Times.Once);
_patientRepositoryMock.Verify(
p => p.InsertOneAsync(It.Is<Patient>(arg =>
arg.UnitId == _unitId &&
arg.PointOfCareId == _pocCinna03Id && arg.PatientNumber == iccaPatients[3].PatientNumber)),
Times.Once);
}
/// <summary>
/// Verifies that when an ICCA patient request is processed and a patient already exists in the database at the same point of care but with a different patient number, the existing patient is updated to the moved point of care and the new ICCA patient is inserted.
/// </summary>
[Test]
public async Task ICCA_Process_Patient_BD_Insert_ICCA_Patient_Pushed_Actual_Patient()
{
var location1 = new PatientLocation("UCI5C", "CINA01");
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var iccaPatients = new List<PatientIcca>
{
new()
{
Location = location1,
PatientNumber = "patientNumber_1",
PatientId = "patientId_1",
AdmitTime = DateTime.Now
}
};
var apiRequest = new ApiRequest
{
Type = "ICCA",
IccaPatients = iccaPatients
};
var patientInBd = new Patient
{
Id = ObjectId.GenerateNewId(),
UnitId = _unitId,
PointOfCareId = _pocCinna01Id,
PatientNumber = patientNumber,
Person = person
};
_patientRepositoryMock.Setup(s => s.FindByPointOfCareId(_pocCinna01Id)).ReturnsAsync(patientInBd);
_patientRepositoryMock.Setup(p => p.FindById(patientInBd.Id)).ReturnsAsync(patientInBd);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.UpdateOneAsync(It.Is<ObjectId>(arg => arg == patientInBd.Id),
It.Is<Patient>(arg => arg.UnitId == _unitId && arg.PointOfCareId == _pocMovedId)),
Times.Once);
_patientRepositoryMock.Verify(
p => p.InsertOneAsync(It.Is<Patient>(arg =>
arg.UnitId == _unitId && arg.PointOfCareId == _pocCinna01Id &&
arg.PatientNumber == iccaPatients[0].PatientNumber)),
Times.Once);
}
/// <summary>
/// Verifies that when processing an ICCA request for a patient already existing in the database
/// and the ICCA patients collection is empty, the existing patient is updated with the UNKNOWN
/// PointOfCareId and no new patient is inserted into the repository.
/// </summary>
[Test]
public async Task ICCA_Process_Patient_BD_No_Insert_ICCA_Patient_UNKNOWN_Actual_Patient()
{
const string patientNumber = "12345";
var person = new Person
{
FirstName = "Miguel", LastName = "Villanueva", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male
};
var iccaPatients = new List<PatientIcca>();
var apiRequest = new ApiRequest
{
Type = "ICCA",
IccaPatients = iccaPatients
};
var patientInBd = new Patient
{
Id = ObjectId.GenerateNewId(),
UnitId = _unitId,
PointOfCareId = _pocCinna01Id,
PatientNumber = patientNumber,
Person = person
};
_patientRepositoryMock.Setup(s => s.FindByPointOfCareId(_pocCinna01Id)).ReturnsAsync(patientInBd);
_patientRepositoryMock.Setup(p => p.FindById(patientInBd.Id)).ReturnsAsync(patientInBd);
await _patientService.SaveRequest(apiRequest);
_patientRepositoryMock.Verify(
p => p.UpdateOneAsync(It.Is<ObjectId>(arg => arg == patientInBd.Id),
It.Is<Patient>(arg => arg.UnitId == _unitId && arg.PointOfCareId == _pocUnknowndId)), Times.Once);
_patientRepositoryMock.Verify(
p => p.InsertOneAsync(It.Is<Patient>(arg =>
arg.UnitId == _unitId &&
arg.PointOfCareId == _pocCinna01Id &&
arg.PatientNumber == iccaPatients[0].PatientNumber)),
Times.Never);
}
//TODO GeTBoxTest
}