using adas_core.Domain.Enums; using adas_core.Domain.Models; using adas_core.Domain.Models.AppSettings; using adas_core.Domain.Models.MongoModels; using adas_core.Infrastructure.Migrations.MongoMigrations; using adas_core.Infrastructure.Repositories; using Microsoft.Extensions.Options; using MongoDB.Bson; using MongoDB.Driver; using MongoMigrations.Core; using Options = Microsoft.Extensions.Options.Options; namespace adas_core.Test.Repositories; [TestFixture] [Category("Integration")] public class MongodbMigrationTest { private PatientRepository _repository; private IOptions _optionsApiSettings; private readonly ApiSettings _apiSettings = new() { ArchivePatientsDiagnosis = "patients" }; private static readonly DateTime Now = DateTime.Now; private static readonly ObjectId PatientId = ObjectId.GenerateNewId(); /// /// Performs one-time initialization for the test fixture by dropping and recreating the "patients" collection, instantiating the PatientRepository, and seeding it with three test Patient records (one of which has a discharge time set to the current time) to verify they are persisted. /// [OneTimeSetUp] public async Task Init() { _optionsApiSettings = Options.Create(_apiSettings); await IntegrationDb.Database.DropCollectionAsync("patients"); await IntegrationDb.Database.CreateCollectionAsync("patients"); _repository = new PatientRepository(_optionsApiSettings, IntegrationDb.Database); var patients = new List { new () { Id = PatientId, PatientId = "patientId1", PointOfCareId = ObjectId.GenerateNewId(), Bed = "bed1", PatientNumber = "patientNumber1", Person = new Person { FirstName = "firstName1", LastName = "lastName1", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male }, DisTime = Now }, new () { PatientId = "patientId2", PointOfCareId = ObjectId.GenerateNewId(), Bed = "bed2", PatientNumber = "patientNumber2", Person = new Person { FirstName = "firstName2", LastName = "lastName2", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male } }, new () { PatientId = "patientId3", PointOfCareId = ObjectId.GenerateNewId(), Bed = "bed3", PatientNumber = "patientNumber3", Person = new Person { FirstName = "firstName3", LastName = "lastName3", BirthDate = new DateTime(), Gender = PatientEnum.Gender.Male } } }; await _repository.InsertManyAsync(patients); Assert.That(await _repository.Collection.CountDocumentsAsync(_ => true), Is.EqualTo(3)); } /// /// Performs one-time cleanup after integration tests by dropping the patients and __migrations collections from the integration database, ensuring a clean state for subsequent test runs. /// [OneTimeTearDown] public void Teardown() { IntegrationDb.Database.DropCollection("patients"); IntegrationDb.Database.DropCollection("__migrations"); } /// /// Verifies that the database is detected as outdated by creating a runner and asserting that IsDatabaseUpToDate returns false when using the primary read preference. /// [Test] [Order(1)] public void IsDatabaseOutdated_ShouldReturnTrue() { var runner = CreateRunner(); var isUpToDate = runner.IsDatabaseUpToDate(ReadPreference.Primary); Assert.That(isUpToDate, Is.False); } /// /// Verifies that after running the migration update to the latest version, the migration with ID 10 (version 0.1.0) is present among the applied migrations. /// [Test] [Order(2)] public void AfterUpdateToLatest_MigrationShouldBeApplied() { var runner = CreateRunner(); runner.UpdateToLatest(); var ids = GetAppliedMigrationIds(); Assert.That(ids, Does.Contain(10)); // 0.1.0 } [Test] public void RunningMigrationsTwice_ShouldNotFail() { var runner = CreateRunner(); runner.UpdateToLatest(); runner.UpdateToLatest(); // segunda ejecución var ids = GetAppliedMigrationIds(); Assert.That(ids, Does.Contain(10)); } // Helpers /// /// Creates and configures a for executing database migrations, using a locator that scans the assembly containing the patient data update migration. /// /// A configured bound to the integration database and the migrations collection. private MigrationRunner CreateRunner() { var locator = new MigrationLocator(); locator.LookForMigrationsInAssembly(typeof(U_0_1_0_UpdateDataPatien).Assembly); return new MigrationRunner( IntegrationDb.Database, collectionName: "__migrations", migrationLocator: locator ); } /// /// Retrieves the identifiers of all applied migrations from the "__migrations" collection in the integration database. /// /// A list of migration identifiers extracted from the "_id" field of each migration document. private List GetAppliedMigrationIds() { var collection = IntegrationDb.Database.GetCollection("__migrations"); return collection .Find(FilterDefinition.Empty) .ToList() .Select(d => d["_id"].AsInt32) .ToList(); } }