using System.Text.RegularExpressions; using LCU.API.Internal.DocumentLib.Containers; using Microsoft.Extensions.Logging; using Moq; using OwnerNumberMigration; using OwnerNumberMigration.Logging; using OwnerNumberMigrationTest.TestDataFactories; using OwnerNumberMigrationTest.TestDoubles; namespace OwnerNumberMigrationTest.Logging; public class AttributeMigrationLoggingDecoratorTest : IDisposable { private readonly IAttributeMigration _decoratedMigration; private readonly string _attributeName = Guid.NewGuid().ToString(); private readonly string _destinationAttributeName = Guid.NewGuid().ToString(); private readonly Mock _rawMigration = new(); private readonly FakeLogger _logger = new(); private readonly FakeMongoCollectionFactory _collectionFactory = new(); private readonly FakeDocumentFilterFactory _filterFactory = new(); public AttributeMigrationLoggingDecoratorTest() { _decoratedMigration = new AttributeMigrationLoggingDecorator ( _rawMigration.Object, _logger, _collectionFactory, _attributeName, _destinationAttributeName, _filterFactory ); } [Test] public async Task Migrate_AllCases_LogsCountToMigrate() { var documentCount = new Random(DateTime.Now.Millisecond).Next(3, 10); var documents = EnumerableDataSeriesFactory .CreateSeries(DocumentInformationFactory.CreateDocumentInformation, documentCount) .ToArray(); await _collectionFactory.GetCollection().InsertManyAsync(documents); _filterFactory.ApplicableDocuments[(_attributeName, _destinationAttributeName)] = documents; await _decoratedMigration.Migrate(new CancellationToken()); Func logMatch = l => l.LogLevel == LogLevel.Information && l.Message.Contains(_attributeName) && new Regex($"\\b{documentCount}\\b").IsMatch(l.Message); Assert.IsTrue(_logger.Logs.Count(logMatch) == 1); } [Test] public async Task Migrate_AllCases_InvokesInnerMigration() { var cancellation = new CancellationToken(); await _decoratedMigration.Migrate(cancellation); _rawMigration.Verify(m => m.Migrate(cancellation), Times.Once); } [Test] public async Task Migrate_InnerMigrationCompletes_LogsElapsedTime() { var migrationDuration = TimeSpan.FromMilliseconds(100); _rawMigration .Setup(m => m.Migrate(It.IsAny())) .Returns(() => Task.Delay(migrationDuration)); var actionStart = DateTime.Now; await _decoratedMigration.Migrate(new CancellationToken()); var elapsed = DateTime.Now - actionStart; Func logMatch = l => { var timespan = Regex.Match(l.Message, "\\d\\d:\\d\\d:\\d\\d\\.\\d\\d\\d\\d\\d\\d\\d"); if (!timespan.Success) return false; var duration = TimeSpan.Parse(timespan.ValueSpan); return l.LogLevel == LogLevel.Information && l.Message.Contains(_attributeName) && duration >= migrationDuration && duration <= elapsed; }; Assert.IsTrue(_logger.Logs.Count(logMatch) == 1); } public void Dispose() { _collectionFactory.Dispose(); } }