adding
This commit is contained in:
+185
@@ -0,0 +1,185 @@
|
||||
using FluentAssertions;
|
||||
using LCU.API.Internal.DocumentLib.Containers;
|
||||
using LCU.API.Internal.DocumentLibTest.TestDoubles;
|
||||
using LCU.Library.Internal.DocumentModels.Requests;
|
||||
using MongoDB.Bson.Serialization;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace LCU.API.Internal.DocumentLibTest.Containers;
|
||||
|
||||
public class DocumentAuditDiscriminatorConventionTest : IDisposable
|
||||
{
|
||||
private readonly FakeMongoCollectionFactory _collectionFactory = new();
|
||||
private readonly IMongoCollection<DocumentAudit> _collection;
|
||||
|
||||
public DocumentAuditDiscriminatorConventionTest()
|
||||
{
|
||||
_collection = _collectionFactory.GetCollection<DocumentAudit>();
|
||||
}
|
||||
|
||||
private static bool _registered = false;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
if (_registered) return;
|
||||
|
||||
BsonSerializer.RegisterDiscriminatorConvention
|
||||
(
|
||||
typeof(DocumentAudit),
|
||||
new DocumentAuditDiscriminatorConvention()
|
||||
);
|
||||
_registered = true;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task FindAuditDocuments_DocumentMissingDiscriminator_DeserializesAsFieldAudit()
|
||||
{
|
||||
var audit = FieldAuditFactory();
|
||||
await _collection.InsertOneAsync(audit);
|
||||
await _collection.FindOneAndUpdateAsync
|
||||
(
|
||||
a => a.DocumentId == audit.DocumentId,
|
||||
Builders<DocumentAudit>.Update.Unset(DocumentAuditDiscriminatorConvention.Discriminator)
|
||||
);
|
||||
|
||||
var retrievedAudit = await
|
||||
(await _collection.FindAsync(a => a.DocumentId == audit.DocumentId))
|
||||
.SingleOrDefaultAsync();
|
||||
|
||||
Assert.IsInstanceOf<DocumentFieldAudit>(retrievedAudit);
|
||||
retrievedAudit.Should().BeEquivalentTo(audit, a => a.Using(DateTimeComparison.Truncated));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task FindAuditDocuments_DiscriminatorIsFieldAudit_DeserializesAsFieldAudit()
|
||||
{
|
||||
var audit = FieldAuditFactory();
|
||||
await _collection.InsertOneAsync(audit);
|
||||
await _collection.FindOneAndUpdateAsync
|
||||
(
|
||||
a => a.DocumentId == audit.DocumentId,
|
||||
Builders<DocumentAudit>.Update.Set
|
||||
(
|
||||
DocumentAuditDiscriminatorConvention.Discriminator,
|
||||
nameof(DocumentFieldAudit)
|
||||
)
|
||||
);
|
||||
|
||||
var retrievedAudit = await
|
||||
(await _collection.FindAsync(a => a.DocumentId == audit.DocumentId))
|
||||
.SingleOrDefaultAsync();
|
||||
|
||||
Assert.IsInstanceOf<DocumentFieldAudit>(retrievedAudit);
|
||||
retrievedAudit.Should().BeEquivalentTo(audit, a => a.Using(DateTimeComparison.Truncated));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task InsertFieldAuditDocuments_NewDocumentWithConventionRegistered_DiscriminatorIsFieldAudit()
|
||||
{
|
||||
var audit = FieldAuditFactory();
|
||||
|
||||
await _collection.InsertOneAsync(audit);
|
||||
|
||||
var audits = await
|
||||
(await _collection.FindAsync
|
||||
(
|
||||
Builders<DocumentAudit>.Filter.Eq
|
||||
(
|
||||
DocumentAuditDiscriminatorConvention.Discriminator,
|
||||
nameof(DocumentFieldAudit)
|
||||
)
|
||||
)
|
||||
)
|
||||
.ToListAsync();
|
||||
audits.Should().ContainEquivalentOf(audit, a => a.Using(DateTimeComparison.Truncated));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task FindAuditDocuments_DiscriminatorIsActionAudit_DeserializesAsActionAudit()
|
||||
{
|
||||
var audit = ActionAuditFactory();
|
||||
await _collection.InsertOneAsync(audit);
|
||||
await _collection.FindOneAndUpdateAsync
|
||||
(
|
||||
a => a.DocumentId == audit.DocumentId,
|
||||
Builders<DocumentAudit>.Update.Set
|
||||
(
|
||||
DocumentAuditDiscriminatorConvention.Discriminator,
|
||||
nameof(DocumentActionAudit)
|
||||
)
|
||||
);
|
||||
|
||||
var retrievedAudit = await
|
||||
(await _collection.FindAsync(a => a.DocumentId == audit.DocumentId))
|
||||
.SingleOrDefaultAsync();
|
||||
|
||||
Assert.IsInstanceOf<DocumentActionAudit>(retrievedAudit);
|
||||
retrievedAudit.Should().BeEquivalentTo(audit, a => a.Using(DateTimeComparison.Truncated));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task InsertActionAuditDocuments_NewDocumentWithConventionRegistered_DiscriminatorIsActionAudit()
|
||||
{
|
||||
var audit = ActionAuditFactory();
|
||||
|
||||
await _collection.InsertOneAsync(audit);
|
||||
|
||||
var audits = await
|
||||
(await _collection.FindAsync
|
||||
(
|
||||
Builders<DocumentAudit>.Filter.Eq
|
||||
(
|
||||
DocumentAuditDiscriminatorConvention.Discriminator,
|
||||
nameof(DocumentActionAudit)
|
||||
)
|
||||
)
|
||||
)
|
||||
.ToListAsync();
|
||||
audits.Should().ContainEquivalentOf(audit, a => a.Using(DateTimeComparison.Truncated));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task FindAuditDocuments_UnknownDiscriminator_ThrowsException()
|
||||
{
|
||||
var audit = FieldAuditFactory();
|
||||
await _collection.InsertOneAsync(audit);
|
||||
await _collection.FindOneAndUpdateAsync
|
||||
(
|
||||
a => a.DocumentId == audit.DocumentId,
|
||||
Builders<DocumentAudit>.Update.Set
|
||||
(
|
||||
DocumentAuditDiscriminatorConvention.Discriminator,
|
||||
Guid.NewGuid().ToString()
|
||||
)
|
||||
);
|
||||
|
||||
Assert.ThrowsAsync<NotSupportedException>(() => _collection.FindAsync(a => a.DocumentId == audit.DocumentId));
|
||||
}
|
||||
|
||||
private static DocumentFieldAudit FieldAuditFactory() => new
|
||||
(
|
||||
Guid.NewGuid(),
|
||||
Guid.NewGuid().ToString(),
|
||||
DateTime.UtcNow,
|
||||
Guid.NewGuid().ToString(),
|
||||
Guid.NewGuid().ToString(),
|
||||
Guid.NewGuid(),
|
||||
Guid.NewGuid()
|
||||
);
|
||||
|
||||
private static DocumentActionAudit ActionAuditFactory() => new
|
||||
(
|
||||
Guid.NewGuid(),
|
||||
Guid.NewGuid().ToString(),
|
||||
DateTime.UtcNow,
|
||||
Guid.NewGuid().ToString(),
|
||||
DocumentAction.Download,
|
||||
Guid.NewGuid().ToString()
|
||||
);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_collectionFactory.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using FluentAssertions;
|
||||
using FluentAssertions.Equivalency;
|
||||
|
||||
namespace LCU.API.Internal.DocumentLibTest;
|
||||
|
||||
public static class DateTimeComparison
|
||||
{
|
||||
public static IEquivalencyStep Truncated { get; } = new TruncatedDateTimeStep();
|
||||
|
||||
public static DateTime Truncate(this DateTime date) => date.AddTicks(-(date.Ticks % 10000));
|
||||
|
||||
private class TruncatedDateTimeStep : IEquivalencyStep
|
||||
{
|
||||
public EquivalencyResult Handle
|
||||
(
|
||||
Comparands comparands,
|
||||
IEquivalencyValidationContext context,
|
||||
IEquivalencyValidator nestedValidator
|
||||
)
|
||||
{
|
||||
if (comparands.Subject is not DateTime subject || comparands.Expectation is not DateTime expectation)
|
||||
return EquivalencyResult.ContinueWithNext;
|
||||
|
||||
subject.Truncate()
|
||||
.Should()
|
||||
.Be(expectation.Truncate(), context.Reason.FormattedMessage, context.Reason.Arguments);
|
||||
|
||||
return EquivalencyResult.AssertionCompleted;
|
||||
}
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" Version="6.7.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||
<PackageReference Include="Mongo2Go" Version="3.1.3" />
|
||||
<PackageReference Include="Moq" Version="4.18.2" />
|
||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||
<PackageReference Include="NUnit.Analyzers" Version="3.3.0" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\LCU.API.Internal.DocumentLib\LCU.API.Internal.DocumentLib.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Repositories\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
using FluentAssertions;
|
||||
using LCU.API.Internal.DocumentLib.Containers;
|
||||
using LCU.API.Internal.DocumentLib.Repositories;
|
||||
using LCU.API.Internal.DocumentLibTest.TestDataFactories;
|
||||
using LCU.API.Internal.DocumentLibTest.TestDoubles;
|
||||
using LCU.Library.Internal.DocumentModels.Requests;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace LCU.API.Internal.DocumentLibTest.Repositories;
|
||||
|
||||
public class DocumentAuditRepositoryTest : IDisposable
|
||||
{
|
||||
private readonly IDocumentAuditRepository _repository;
|
||||
|
||||
private readonly FakeMongoCollectionFactory _collectionFactory = new();
|
||||
|
||||
public DocumentAuditRepositoryTest()
|
||||
{
|
||||
_repository = new DocumentAuditRepository(_collectionFactory);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetDocumentAudits_FieldAuditRecordsExistForId_ReturnsMatchedLogsById()
|
||||
{
|
||||
var audits = EnumerableDataSeriesFactory.CreateSeries(() => FieldAuditFactory(), 5).ToArray();
|
||||
await _collectionFactory.GetCollection<DocumentAudit>().InsertManyAsync(audits);
|
||||
var expectedAudits = new[]{ audits.First(), audits.Last() };
|
||||
var documentIds = expectedAudits.Select(a => a.DocumentId).ToArray();
|
||||
|
||||
var retrievedAudits = await _repository.GetDocumentAudits(documentIds);
|
||||
|
||||
retrievedAudits.Should().HaveSameCount(documentIds);
|
||||
expectedAudits.Should().BeEquivalentTo(retrievedAudits, a => a.Using(DateTimeComparison.Truncated));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetDocumentAudits_ActionAuditRecordsExistForId_ReturnsMatchedLogsById()
|
||||
{
|
||||
var audits = EnumerableDataSeriesFactory.CreateSeries(() => ActionAuditFactory(), 5).ToArray();
|
||||
await _collectionFactory.GetCollection<DocumentAudit>().InsertManyAsync(audits);
|
||||
var expectedAudits = new[] { audits.First(), audits.Last() };
|
||||
var documentIds = expectedAudits.Select(a => a.DocumentId).ToArray();
|
||||
|
||||
var retrievedAudits = await _repository.GetDocumentAudits(documentIds);
|
||||
|
||||
retrievedAudits.Should().HaveSameCount(documentIds);
|
||||
expectedAudits.Should().BeEquivalentTo(retrievedAudits, a => a.Using(DateTimeComparison.Truncated));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task SaveDocumentAudits_FieldAuditsSubmitted_SavesAll()
|
||||
{
|
||||
var audits = EnumerableDataSeriesFactory.CreateSeries(() => FieldAuditFactory(), 5).ToArray();
|
||||
|
||||
await _repository.SaveDocumentAudits(audits);
|
||||
|
||||
var savedAudits = await (
|
||||
await _collectionFactory
|
||||
.GetCollection<DocumentAudit>()
|
||||
.FindAsync(Builders<DocumentAudit>.Filter.In
|
||||
(
|
||||
nameof(DocumentAudit.DocumentId),
|
||||
audits.Select(a => a.DocumentId))
|
||||
)
|
||||
).ToListAsync();
|
||||
audits.Should().BeEquivalentTo(savedAudits, a => a.Using(DateTimeComparison.Truncated));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task SaveDocumentAudits_ActionAuditsSubmitted_SavesAll()
|
||||
{
|
||||
var audits = EnumerableDataSeriesFactory.CreateSeries(() => ActionAuditFactory(), 5).ToArray();
|
||||
|
||||
await _repository.SaveDocumentAudits(audits);
|
||||
|
||||
var savedAudits = await (
|
||||
await _collectionFactory
|
||||
.GetCollection<DocumentAudit>()
|
||||
.FindAsync(Builders<DocumentAudit>.Filter.In(nameof(DocumentAudit.DocumentId),
|
||||
audits.Select(a => a.DocumentId)))
|
||||
).ToListAsync();
|
||||
audits.Should().BeEquivalentTo(savedAudits, a => a.Using(DateTimeComparison.Truncated));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task SaveDocumentAudits_MultipleTypesOfAudits_CanRetrieveAll()
|
||||
{
|
||||
var documentId = Guid.NewGuid();
|
||||
var fieldAudits = EnumerableDataSeriesFactory.CreateSeries<DocumentAudit>(() => FieldAuditFactory(documentId), 5);
|
||||
var actionAudits = EnumerableDataSeriesFactory.CreateSeries<DocumentAudit>(() => ActionAuditFactory(documentId), 5);
|
||||
var audits = fieldAudits.Concat(actionAudits).ToArray();
|
||||
|
||||
await _repository.SaveDocumentAudits(audits);
|
||||
var savedAudits = await _repository.GetDocumentAudits(documentId);
|
||||
|
||||
audits.Should().BeEquivalentTo(savedAudits, a => a.Using(DateTimeComparison.Truncated));
|
||||
}
|
||||
|
||||
private static DocumentFieldAudit FieldAuditFactory(Guid? documentId = null) => new
|
||||
(
|
||||
documentId ?? Guid.NewGuid(),
|
||||
Guid.NewGuid().ToString(),
|
||||
DateTime.UtcNow,
|
||||
Guid.NewGuid().ToString(),
|
||||
Guid.NewGuid().ToString(),
|
||||
Guid.NewGuid().ToString(),
|
||||
Guid.NewGuid().ToString()
|
||||
);
|
||||
|
||||
private static DocumentActionAudit ActionAuditFactory(Guid? documentId = null) => new
|
||||
(
|
||||
documentId ?? Guid.NewGuid(),
|
||||
Guid.NewGuid().ToString(),
|
||||
DateTime.UtcNow,
|
||||
Guid.NewGuid().ToString(),
|
||||
(DocumentAction)DateTime.Now.Millisecond,
|
||||
Guid.NewGuid().ToString()
|
||||
);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_collectionFactory.Dispose();
|
||||
}
|
||||
}
|
||||
+1230
File diff suppressed because it is too large
Load Diff
+33
@@ -0,0 +1,33 @@
|
||||
using LCU.API.Internal.DocumentLib.Containers;
|
||||
|
||||
namespace LCU.API.Internal.DocumentLibTest.TestDataFactories;
|
||||
|
||||
public static class DocumentInformationFactory
|
||||
{
|
||||
public static DocumentInformation CreateDocumentInformation() => new()
|
||||
{
|
||||
DocumentId = Guid.NewGuid(),
|
||||
DocumentBlobId = Guid.NewGuid(),
|
||||
TraceId = Guid.NewGuid(),
|
||||
Name = Guid.NewGuid().ToString(),
|
||||
Type = Guid.NewGuid().ToString(),
|
||||
Source = Guid.NewGuid().ToString(),
|
||||
DataSource = Guid.NewGuid().ToString(),
|
||||
FileSize = DateTime.Now.Millisecond,
|
||||
ScanStatus = DateTime.Now.Millisecond % 2 == 0,
|
||||
UploadDate = DateTime.UtcNow,
|
||||
LastModifiedDate = DateTime.UtcNow,
|
||||
CreatedDate = DateTime.UtcNow,
|
||||
PersonNumbers = new[] { Guid.NewGuid().ToString(), Guid.NewGuid().ToString() },
|
||||
OrganizationNumbers = new []{ Guid.NewGuid().ToString() , Guid.NewGuid().ToString() },
|
||||
AccountNumber = Guid.NewGuid().ToString(),
|
||||
Attributes = new Dictionary<string, string>
|
||||
{
|
||||
["PersonNumber"] = Guid.NewGuid().ToString(),
|
||||
["PersonNumbers"] = $"{Guid.NewGuid()},{Guid.NewGuid()}",
|
||||
["OrganizationNumber"] = Guid.NewGuid().ToString(),
|
||||
["OrganizationNumbers"] = $"{Guid.NewGuid()},{Guid.NewGuid()}",
|
||||
["AccountNumber"] = Guid.NewGuid().ToString()
|
||||
},
|
||||
};
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
namespace LCU.API.Internal.DocumentLibTest.TestDataFactories;
|
||||
|
||||
public static class EnumerableDataSeriesFactory
|
||||
{
|
||||
public static IEnumerable<T> CreateSeries<T>(Func<T> singleFactory, int count) => Enumerable
|
||||
.Repeat(singleFactory, count)
|
||||
.Select(f => f());
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
using LCU.API.Internal.DocumentLib.Utilities;
|
||||
using Mongo2Go;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace LCU.API.Internal.DocumentLibTest.TestDoubles;
|
||||
|
||||
public class FakeMongoCollectionFactory : IMongoCollectionFactory, IDisposable
|
||||
{
|
||||
private readonly MongoDbRunner _runner = MongoDbRunner.Start();
|
||||
|
||||
public IMongoCollection<T> GetCollection<T>() => new MongoClient(_runner.ConnectionString)
|
||||
.GetDatabase(typeof(T).Name)
|
||||
.GetCollection<T>(typeof(T).Name);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_runner.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
global using NUnit.Framework;
|
||||
Reference in New Issue
Block a user