adding
This commit is contained in:
+25
@@ -0,0 +1,25 @@
|
||||
using LCU.API.Internal.DocumentLib.Containers;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using OwnerNumberMigration.Migrations;
|
||||
using OwnerNumberMigration.ValueParsing;
|
||||
using OwnerNumberMigration;
|
||||
|
||||
namespace OwnerNumberMigrationTest.Migrations;
|
||||
|
||||
public class AccountNumberMigrationTest : AttributeMigrationTaskTest<string>
|
||||
{
|
||||
protected override string SourceAttribute => "AccountNumber";
|
||||
|
||||
protected override string DestinationAttribute => nameof(DocumentInformation.AccountNumber);
|
||||
|
||||
protected override IHostedService MigrationTaskFactory
|
||||
(
|
||||
AttributeMigrationFactory<string> factory,
|
||||
IParsingStrategyFactory strategyFactory,
|
||||
IMigrationManager manager
|
||||
) => new AccountNumberMigration(factory, strategyFactory, manager);
|
||||
|
||||
public AccountNumberMigrationTest() : base(() => string.Empty)
|
||||
{
|
||||
}
|
||||
}
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Moq;
|
||||
using OwnerNumberMigration;
|
||||
using OwnerNumberMigration.Migrations;
|
||||
using OwnerNumberMigration.ValueParsing;
|
||||
using OwnerNumberMigrationTest.TestDoubles;
|
||||
|
||||
namespace OwnerNumberMigrationTest.Migrations;
|
||||
|
||||
public abstract class AttributeMigrationTaskTest<T>
|
||||
{
|
||||
protected abstract IHostedService MigrationTaskFactory
|
||||
(
|
||||
AttributeMigrationFactory<T> factory,
|
||||
IParsingStrategyFactory strategyFactory,
|
||||
IMigrationManager manager
|
||||
);
|
||||
private IHostedService MigrationServiceFactory() => MigrationTaskFactory
|
||||
(
|
||||
(_, _, _) => _migration.Object,
|
||||
StrategyFactory.Object,
|
||||
_manager.Object
|
||||
);
|
||||
|
||||
protected abstract string SourceAttribute { get; }
|
||||
protected abstract string DestinationAttribute { get; }
|
||||
|
||||
protected readonly Mock<IParsingStrategyFactory> StrategyFactory = new();
|
||||
private readonly FakeParsingStrategy<T> _parsingStrategy;
|
||||
private readonly Mock<IAttributeMigration> _migration = new();
|
||||
private readonly Mock<IMigrationManager> _manager = new();
|
||||
|
||||
protected AttributeMigrationTaskTest(Func<T> newT)
|
||||
{
|
||||
_parsingStrategy = new FakeParsingStrategy<T>(newT);
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
StrategyFactory
|
||||
.Setup(f => f.CreateParsingStrategy<T>(SourceAttribute))
|
||||
.Returns((IValueParsingStrategy<T>)_parsingStrategy);
|
||||
|
||||
_migration.Reset();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Constructor_AllCases_CreatesMigrationWithJobTypeAttributes()
|
||||
{
|
||||
string? sourceAttribute = null;
|
||||
string? destinationAttribute = null;
|
||||
IValueParsingStrategy<T>? parsingStrategy = null;
|
||||
|
||||
MigrationTaskFactory
|
||||
(
|
||||
(source, strategy, destination) =>
|
||||
{
|
||||
sourceAttribute = source;
|
||||
parsingStrategy = strategy;
|
||||
destinationAttribute = destination;
|
||||
|
||||
return _migration.Object;
|
||||
},
|
||||
StrategyFactory.Object,
|
||||
_manager.Object
|
||||
);
|
||||
|
||||
Assert.AreEqual(SourceAttribute, sourceAttribute);
|
||||
Assert.AreSame(_parsingStrategy, parsingStrategy);
|
||||
Assert.AreEqual(DestinationAttribute, destinationAttribute);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task StartAsync_TokenCancelled_DoesNotStartMigration()
|
||||
{
|
||||
var cancellation = new CancellationToken(true);
|
||||
var migration = MigrationServiceFactory();
|
||||
|
||||
await migration.StartAsync(cancellation);
|
||||
|
||||
_migration.Verify(m => m.Migrate(It.IsAny<CancellationToken>()), Times.Never);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task StartAsync_NotCanceled_StartsMigrationTaskAndReturns()
|
||||
{
|
||||
var cancellation = new CancellationToken();
|
||||
_migration
|
||||
.Setup(m => m.Migrate(It.IsAny<CancellationToken>()))
|
||||
.Returns<CancellationToken>(async token =>
|
||||
{
|
||||
await Task.Delay(TimeSpan.MaxValue, token);
|
||||
}
|
||||
);
|
||||
var migration = MigrationServiceFactory();
|
||||
|
||||
await migration.StartAsync(cancellation);
|
||||
|
||||
_migration.Verify(m => m.Migrate(It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task StartAsync_NotCanceled_RegistersMigrationTaskWithManager()
|
||||
{
|
||||
var cancellation = new CancellationToken();
|
||||
var migrationTask = Task.Run(() => { });
|
||||
_migration
|
||||
.Setup(m => m.Migrate(It.IsAny<CancellationToken>()))
|
||||
.Returns(migrationTask);
|
||||
var migration = MigrationServiceFactory();
|
||||
|
||||
await migration.StartAsync(cancellation);
|
||||
|
||||
_manager.Verify(m => m.Start(migrationTask), Times.Once);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task StopAsync_NotStarted_ReturnsWithoutError()
|
||||
{
|
||||
var cancellation = new CancellationToken();
|
||||
var migration = MigrationServiceFactory();
|
||||
|
||||
Assert.DoesNotThrowAsync(() => migration.StopAsync(cancellation));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task StopAsync_AlreadyCompleted_CleansUpMigrationTask()
|
||||
{
|
||||
var cancellation = new CancellationToken();
|
||||
Task? migrationTask = null;
|
||||
_migration
|
||||
.Setup(m => m.Migrate(It.IsAny<CancellationToken>()))
|
||||
.Returns<CancellationToken>(token => migrationTask = Task.Run
|
||||
(
|
||||
() => { },
|
||||
token
|
||||
));
|
||||
var migration = MigrationServiceFactory();
|
||||
|
||||
await migration.StartAsync(cancellation);
|
||||
await migrationTask;
|
||||
await migration.StopAsync(cancellation);
|
||||
|
||||
Assert.AreEqual(TaskStatus.RanToCompletion, migrationTask.Status);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task StopAsync_NotCompleted_CancelsMigrationTaskThenCleansUp()
|
||||
{
|
||||
var cancellation = new CancellationToken();
|
||||
Task? migrationTask = null;
|
||||
_migration
|
||||
.Setup(m => m.Migrate(It.IsAny<CancellationToken>()))
|
||||
.Returns<CancellationToken>(token => migrationTask = Task.Run
|
||||
(
|
||||
async () =>
|
||||
{
|
||||
await Task.Delay(-1, token);
|
||||
},
|
||||
token
|
||||
));
|
||||
var migration = MigrationServiceFactory();
|
||||
|
||||
await migration.StartAsync(cancellation);
|
||||
await migration.StopAsync(cancellation);
|
||||
|
||||
Assert.AreEqual(TaskStatus.Canceled, migrationTask.Status);
|
||||
}
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Moq;
|
||||
using OwnerNumberMigration.Migrations;
|
||||
using OwnerNumberMigrationTest.TestDataFactories;
|
||||
|
||||
namespace OwnerNumberMigrationTest.Migrations;
|
||||
|
||||
public class MigrationManagerTest
|
||||
{
|
||||
private readonly IMigrationManager _manager;
|
||||
|
||||
private readonly Mock<IHostApplicationLifetime> _lifetime = new();
|
||||
|
||||
public MigrationManagerTest()
|
||||
{
|
||||
_manager = new MigrationManager(_lifetime.Object);
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_lifetime.Reset();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Start_OneTaskThatFinishes_EndsApplication()
|
||||
{
|
||||
var applicationStopped = new SemaphoreSlim(0);
|
||||
_lifetime
|
||||
.Setup(l => l.StopApplication())
|
||||
.Callback(() => applicationStopped.Release());
|
||||
var task = Task.CompletedTask;
|
||||
|
||||
_manager.Start(task);
|
||||
|
||||
await applicationStopped.WaitAsync(TimeSpan.FromMilliseconds(50));
|
||||
_lifetime.Verify(l => l.StopApplication(), Times.AtLeastOnce);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Start_OneTaskThatCancels_EndsApplication()
|
||||
{
|
||||
var applicationStopped = new SemaphoreSlim(0);
|
||||
_lifetime
|
||||
.Setup(l => l.StopApplication())
|
||||
.Callback(() => applicationStopped.Release());
|
||||
var task = Task.FromCanceled(new CancellationToken(true));
|
||||
|
||||
_manager.Start(task);
|
||||
|
||||
await applicationStopped.WaitAsync(TimeSpan.FromMilliseconds(50));
|
||||
_lifetime.Verify(l => l.StopApplication(), Times.AtLeastOnce);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Start_OneTaskThatErrors_EndsApplication()
|
||||
{
|
||||
var applicationStopped = new SemaphoreSlim(0);
|
||||
_lifetime
|
||||
.Setup(l => l.StopApplication())
|
||||
.Callback(() => applicationStopped.Release());
|
||||
_lifetime
|
||||
.Setup(l => l.StopApplication())
|
||||
.Callback(() => applicationStopped.Release());
|
||||
var task = Task.FromException(new Exception());
|
||||
|
||||
_manager.Start(task);
|
||||
|
||||
await applicationStopped.WaitAsync(TimeSpan.FromMilliseconds(50));
|
||||
_lifetime.Verify(l => l.StopApplication(), Times.AtLeastOnce);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Start_MultipleTasksThatFinish_EndsApplicationAfterAll()
|
||||
{
|
||||
var applicationStopped = new SemaphoreSlim(0);
|
||||
_lifetime
|
||||
.Setup(l => l.StopApplication())
|
||||
.Callback(() => applicationStopped.Release());
|
||||
var semaphores = EnumerableDataSeriesFactory
|
||||
.CreateSeries(() => new SemaphoreSlim(0), 5)
|
||||
.ToArray();
|
||||
var tasks = semaphores
|
||||
.Select(s => Task.Run(async () => await s.WaitAsync()))
|
||||
.ToArray();
|
||||
|
||||
foreach(var task in tasks) _manager.Start(task);
|
||||
|
||||
_lifetime.Verify(l => l.StopApplication(), Times.Never);
|
||||
foreach (var semaphore in semaphores[..^1])
|
||||
{
|
||||
semaphore.Release();
|
||||
_lifetime.Verify(l => l.StopApplication(), Times.Never);
|
||||
}
|
||||
foreach (var semaphore in semaphores[^1..])
|
||||
{
|
||||
semaphore.Release();
|
||||
}
|
||||
await applicationStopped.WaitAsync(TimeSpan.FromMilliseconds(50));
|
||||
_lifetime.Verify(l => l.StopApplication(), Times.AtLeastOnce);
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
using LCU.API.Internal.DocumentLib.Containers;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using OwnerNumberMigration;
|
||||
using OwnerNumberMigration.Migrations;
|
||||
using OwnerNumberMigration.ValueParsing;
|
||||
|
||||
namespace OwnerNumberMigrationTest.Migrations;
|
||||
|
||||
public class OrganizationNumberMigrationTest : AttributeMigrationTaskTest<string[]>
|
||||
{
|
||||
protected override string SourceAttribute => "OrganizationNumber";
|
||||
|
||||
protected override string DestinationAttribute => nameof(DocumentInformation.OrganizationNumbers);
|
||||
|
||||
protected override IHostedService MigrationTaskFactory
|
||||
(
|
||||
AttributeMigrationFactory<string[]> factory,
|
||||
IParsingStrategyFactory strategyFactory,
|
||||
IMigrationManager manager
|
||||
) => new OrganizationNumberMigration(factory, strategyFactory, manager);
|
||||
|
||||
public OrganizationNumberMigrationTest() : base(Array.Empty<string>)
|
||||
{
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using OwnerNumberMigration.Migrations;
|
||||
using OwnerNumberMigration;
|
||||
using OwnerNumberMigration.ValueParsing;
|
||||
using LCU.API.Internal.DocumentLib.Containers;
|
||||
|
||||
namespace OwnerNumberMigrationTest.Migrations;
|
||||
|
||||
public class OrganizationNumbersMigrationTest : AttributeMigrationTaskTest<string[]>
|
||||
{
|
||||
protected override string SourceAttribute => "OrganizationNumbers";
|
||||
|
||||
protected override string DestinationAttribute => nameof(DocumentInformation.OrganizationNumbers);
|
||||
|
||||
protected override IHostedService MigrationTaskFactory
|
||||
(
|
||||
AttributeMigrationFactory<string[]> factory,
|
||||
IParsingStrategyFactory strategyFactory,
|
||||
IMigrationManager manager
|
||||
) => new OrganizationNumbersMigration(factory, strategyFactory, manager);
|
||||
|
||||
public OrganizationNumbersMigrationTest() : base(Array.Empty<string>)
|
||||
{
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using OwnerNumberMigration.Migrations;
|
||||
using OwnerNumberMigration;
|
||||
using OwnerNumberMigration.ValueParsing;
|
||||
using LCU.API.Internal.DocumentLib.Containers;
|
||||
|
||||
namespace OwnerNumberMigrationTest.Migrations;
|
||||
|
||||
public class PersonNumberMigrationTest : AttributeMigrationTaskTest<string[]>
|
||||
{
|
||||
protected override string SourceAttribute => "PersonNumber";
|
||||
|
||||
protected override string DestinationAttribute => nameof(DocumentInformation.PersonNumbers);
|
||||
|
||||
protected override IHostedService MigrationTaskFactory
|
||||
(
|
||||
AttributeMigrationFactory<string[]> factory,
|
||||
IParsingStrategyFactory strategyFactory,
|
||||
IMigrationManager manager
|
||||
) => new PersonNumberMigration(factory, strategyFactory, manager);
|
||||
|
||||
public PersonNumberMigrationTest() : base(Array.Empty<string>)
|
||||
{
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using OwnerNumberMigration.Migrations;
|
||||
using OwnerNumberMigration;
|
||||
using OwnerNumberMigration.ValueParsing;
|
||||
using LCU.API.Internal.DocumentLib.Containers;
|
||||
|
||||
namespace OwnerNumberMigrationTest.Migrations;
|
||||
|
||||
public class PersonNumbersMigrationTest : AttributeMigrationTaskTest<string[]>
|
||||
{
|
||||
protected override string SourceAttribute => "PersonNumbers";
|
||||
|
||||
protected override string DestinationAttribute => nameof(DocumentInformation.PersonNumbers);
|
||||
|
||||
protected override IHostedService MigrationTaskFactory
|
||||
(
|
||||
AttributeMigrationFactory<string[]> factory,
|
||||
IParsingStrategyFactory strategyFactory,
|
||||
IMigrationManager manager
|
||||
) => new PersonNumbersMigration(factory, strategyFactory, manager);
|
||||
|
||||
public PersonNumbersMigrationTest() : base(Array.Empty<string>)
|
||||
{
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user