using System.Security.Claims; using adas_core.Application.Exceptions; using adas_core.Application.Repositories.Interfaces; using adas_core.Application.Services; using adas_core.Application.Services.Interfaces; using adas_core.Domain.Enums; using adas_core.Domain.Models; using adas_core.Domain.Models.Masters; using adas_core.Domain.Models.MongoModels; using adas_core.Test.Utilities; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using MongoDB.Bson; using Moq; namespace adas_core.Test.Services; /// /// Contains unit tests for verifying the behavior of the class. /// public class AdmissionServiceTest { private Mock _admissionRepositoryMock; private AdmissionService _admissionService; private Mock _auditServiceMock; private Mock _clientMessageServiceMock; private Mock _dischargeServiceMock; private Mock _displayServiceMock; //Logs de auditoria private Mock _httpContextAccessorMock; private Mock> _loggerMock; private Mock _masterListServiceFactoryMock; private Mock _patientArchiveRepoMock; private Mock _patientServiceMock; private Mock _pointOfCareServiceMock; private Mock _subscribersServiceMock; private Mock _unitServiceMock; [SetUp] public void Setup() { _loggerMock = new Mock>(); _subscribersServiceMock = new Mock(); _admissionRepositoryMock = new Mock(); _pointOfCareServiceMock = new Mock(); _clientMessageServiceMock = new Mock(); _unitServiceMock = new Mock(); _patientServiceMock = new Mock(); _displayServiceMock = new Mock(); _dischargeServiceMock = new Mock(); _patientArchiveRepoMock = new Mock(); _auditServiceMock = new Mock(); _httpContextAccessorMock = new Mock(); _masterListServiceFactoryMock = new Mock(); // Simulación de contexto HTTP y usuario autenticado 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); _admissionService = new AdmissionService(_loggerMock.Object, _subscribersServiceMock.Object, _admissionRepositoryMock.Object, _clientMessageServiceMock.Object, _unitServiceMock.Object, _patientServiceMock.Object, _pointOfCareServiceMock.Object, _displayServiceMock.Object, _dischargeServiceMock.Object, _patientArchiveRepoMock.Object, _httpContextAccessorMock.Object, _auditServiceMock.Object, _masterListServiceFactoryMock.Object); } /// /// 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. /// [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); } /// /// Verifies that DeleteAdmissionByIdAsync successfully deletes an admission when it exists in the repository, by ensuring the repository's Delete method is invoked exactly once for the given admission identifier. /// [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); } /// /// Verifies that 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. /// [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())) .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")); } /// /// Verifies that GetAdmissionsAsync returns admissions enriched with their associated patient location details /// retrieved from the point of care service. /// [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 { admission1, admission2 }; _admissionRepositoryMock.Setup(repo => repo.FindAll()) .ReturnsAsync(admissionsList); _pointOfCareServiceMock.Setup(repo => repo.GetInfo(poc1Id, null, false, It.IsAny())) .ReturnsAsync(TestUtilities.CreateValidPointOfCare()); _pointOfCareServiceMock.Setup(repo => repo.GetInfo(poc2Id, null, false, It.IsAny())) .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() // { // // Arrange // var admission = new Admission // { // Id = ObjectId.GenerateNewId(), // AdmissionDate = DateTime.UtcNow, // Nhc = "TestNhc", // PointOfCareId = ObjectId.GenerateNewId(), // Person = new Person(), // Origin = TestUtilities.CreateValidOptionList(), // Diagnosis = TestUtilities.CreateValidOptionList(), // Allergies = new List { TestUtilities.CreateValidOptionList() }, // Insulation = TestUtilities.CreateValidOptionList(), // LanguageBarrier = TestUtilities.CreateValidOptionList() // }; // // var pointOfCare = TestUtilities.CreateValidPointOfCare(); // // // Setup the pointOfCareServiceMock to return a valid point of care // pointOfCareServiceMock // .Setup(repo => repo.GetInfo(It.IsAny())) // .ReturnsAsync(pointOfCare); // // // Act // var result = await admissionService.InsertAdmission(admission); // // // Assert // Assert.That(result, Is.Not.Null); // Assert.That(result, Is.EqualTo(admission)); // admissionRepositoryMock.Verify(repo => repo.InsertOneAsyncAndReturn(It.IsAny()), Times.Once); // pointOfCareServiceMock.Verify(repo => repo.Update(It.IsAny()), Times.Once); // } /// /// Verifies that .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. /// [Test] public async Task UpdateAdmissionAsync_WhenAdmissionExists_UpdatesAdmission() { // 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())) .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()), Times.Once); _pointOfCareServiceMock.Verify(repo => repo.GetInfo(oldAdmission.PointOfCareId.Value, null, false, It.IsAny()), Times.Once); } /// /// 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. /// [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())) .ReturnsAsync((ObjectId id) => id == admission.PointOfCareId ? pointOfCare : null); // Act await _admissionService.AdmitPatient(admission); // Assert _patientServiceMock.Verify(repo => repo.Insert(It.IsAny()), Times.Once); } /// /// 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. /// [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 { 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)); } /// /// Verifies that returns an empty result when the requested location does not exist, simulating the not-found scenario by having the repository throw an exception. /// [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); } /// /// Verifies that when a Point of Care exists for the given identifier, the admissions returned by /// GetAdmissionByPointOfCareId are enriched with patient location details (unit name, bed, and room) /// retrieved from the corresponding Point of Care entity. /// [Test] public async Task GetAdmissionByPointOfCareId_POCExists_ReturnsAdmissionsWithLocation() { // Arrange var pocId = ObjectId.GenerateNewId(); var expectedAdmissions = new List { 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())) .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)); } } /// /// Verifies that returns an empty result when the underlying repository throws an exception while attempting to find an admission by point of care id. /// [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); } /// /// Verifies that returns the expected list of admissions /// when a valid unit identifier is provided. /// [Test] public async Task GetAdmissionByUnitIdWithOutPoC_UnitIdExists_ReturnsAdmissions() { // Arrange var unitId = ObjectId.GenerateNewId(); var expectedAdmissions = new List { 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)); } /// /// Verifies that GetAdmissionByUnitIdWithOutPoC returns an empty result when the underlying repository /// throws an exception while looking up the given unit identifier. /// /// The identifier of the unit whose admission record is being requested. [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() // { // // Arrange // var apiRequest = new ApiRequest // { // Type = "NewAdmission", // Admission = new Admission // { // Id = ObjectId.GenerateNewId(), // Nhc = "TestNhc", // Origin = new OptionList(), // Diagnosis = new OptionList() // } // }; // // admissionServiceMock.Setup(service => service.InsertAdmission(apiRequest.Admission)) // .Verifiable(); // // // Act // await admissionService.SaveRequest(apiRequest); // // // Assert // admissionServiceMock.Verify(service => service.InsertAdmission(apiRequest.Admission), Times.Once); // } // [Test] // public async Task SaveRequest_UpdateAdmission_ValidRequest_UpdatesAdmission() // { // // Arrange // var apiRequest = new ApiRequest // { // Type = "UpdateAdmission", // Admission = new Admission // { // Id = ObjectId.GenerateNewId(), // Nhc = "TestNhc", // Origin = new OptionList(), // Diagnosis = new OptionList() // } // }; // // admissionServiceMock.Setup(service => service.UpdateAdmissionAsync(apiRequest.Admission)) // .Verifiable(); // // // Act // await admissionService.SaveRequest(apiRequest); // // // Assert // admissionServiceMock.Verify(service => service.UpdateAdmissionAsync(apiRequest.Admission), Times.Once); // } // [Test] // public async Task SaveRequest_DeleteAdmission_ValidRequest_DeletesAdmission() // { // // Arrange // var apiRequest = new ApiRequest // { // Type = "DeleteAdmission", // Admission = new Admission { Id = ObjectId.GenerateNewId() } // }; // // admissionServiceMock.Setup(service => service.DeleteAdmissionAsync(apiRequest.Admission)) // .Verifiable(); // // // Act // await admissionService.SaveRequest(apiRequest); // // // Assert // admissionServiceMock.Verify(service => service.DeleteAdmissionAsync(apiRequest.Admission), Times.Once); // } // [Test] // public async Task SaveRequestAsync_Calls_SaveRequest_Method() // { // // Arrange // var apiRequest = new ApiRequest // { // Type = "NewAdmission", // Admission = new Admission // { // Id = ObjectId.GenerateNewId(), // Nhc = "TestNhc", // Origin = new OptionList(), // Diagnosis = new OptionList() // } // }; // // admissionServiceMock.Setup(service => service.SaveRequest(apiRequest)) // .Returns(Task.CompletedTask) // Since SaveRequest is async, returning completed task for simplicity // .Verifiable(); // // // Act // await admissionService.SaveRequestAsync(apiRequest); // // // Assert // admissionServiceMock.Verify(service => service.SaveRequest(apiRequest), Times.Once); // } /// /// 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. /// [Test] public async Task InsertAdmission_ValidAdmission_InsertsSuccessfullyWithUser() { // 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())) .ReturnsAsync(pointOfCare); _admissionRepositoryMock .Setup(repo => repo.InsertOneAsyncAndReturn(admission)) .ReturnsAsync(admission); Func act = () => _admissionService.InsertAdmission(admission); var ex = Assert.ThrowsAsync(act); Assert.That(ex!.Message, Is.EqualTo(((int)HttpEnum.ErrorMessage.NotFoundResourceMissing).ToString())); // Verify no insert _admissionRepositoryMock .Verify(repo => repo.InsertOneAsyncAndReturn(It.IsAny()), Times.Never); // Verify no update _pointOfCareServiceMock .Verify(service => service.Update(It.IsAny()), Times.Never); } }