diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e10312d..75cb869 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,36 +43,6 @@ jobs: dotnet-version: | 6.0.x 8.0.x - - name: Setup PowerShell (Ubuntu) - if: matrix.os == 'ubuntu-latest' - run: | - dotnet tool install --global PowerShell - - name: Find latest PowerShell version (Windows) - if: matrix.os == 'windows-latest' - shell: pwsh - run: | - $packageName = "powershell" - $outputText = dotnet tool search $packageName --take 1 - $outputLine = ("" + $outputText) - $indexOfVersionLine = $outputLine.IndexOf($packageName) - $latestVersion = $outputLine.substring($indexOfVersionLine + $packageName.length).trim().split(" ")[0].trim() - - Write-Output "Found PowerShell version: $latestVersion" - Write-Output "POWERSHELL_LATEST_VERSION=$latestVersion" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - - name: Setup PowerShell (Windows) - if: matrix.os == 'windows-latest' - shell: cmd - run: | - set DOWNLOAD_LINK=https://github.com/PowerShell/PowerShell/releases/download/v%POWERSHELL_LATEST_VERSION%/PowerShell-%POWERSHELL_LATEST_VERSION%-win-x64.msi - set OUTPUT_PATH=%RUNNER_TEMP%\PowerShell-%POWERSHELL_LATEST_VERSION%-win-x64.msi - echo Downloading from: %DOWNLOAD_LINK% to: %OUTPUT_PATH% - curl --location --output %OUTPUT_PATH% %DOWNLOAD_LINK% - msiexec.exe /package %OUTPUT_PATH% /quiet USE_MU=1 ENABLE_MU=1 ADD_PATH=1 DISABLE_TELEMETRY=1 - - name: Setup PowerShell (macOS) - if: matrix.os == 'macos-latest' - run: | - /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" - brew install --cask powershell - name: Show installed versions shell: pwsh run: | @@ -235,13 +205,13 @@ jobs: $baseCommitHash = git rev-parse HEAD~1 Write-Output "Running code cleanup on commit range $baseCommitHash..$headCommitHash in pull request." - dotnet regitlint -s JsonApiDotNetCore.MongoDb.sln --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --verbosity=WARN -f commits -a $headCommitHash -b $baseCommitHash --fail-on-diff --print-diff + dotnet regitlint -s JsonApiDotNetCore.MongoDb.sln --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN -f commits -a $headCommitHash -b $baseCommitHash --fail-on-diff --print-diff - name: CleanupCode (on branch) if: github.event_name == 'push' || github.event_name == 'release' shell: pwsh run: | Write-Output "Running code cleanup on all files." - dotnet regitlint -s JsonApiDotNetCore.MongoDb.sln --print-command --skip-tool-check --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --verbosity=WARN --fail-on-diff --print-diff + dotnet regitlint -s JsonApiDotNetCore.MongoDb.sln --print-command --skip-tool-check --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN --fail-on-diff --print-diff publish: timeout-minutes: 60 diff --git a/Directory.Build.props b/Directory.Build.props index d13bf29..a30d43f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -27,6 +27,6 @@ false $(MSBuildThisFileDirectory)CodingGuidelines.ruleset $(MSBuildThisFileDirectory)tests.runsettings - 5.5.1 + 5.6.0 diff --git a/JsonApiDotNetCore.MongoDb.sln b/JsonApiDotNetCore.MongoDb.sln index 81b5b78..83efaf6 100644 --- a/JsonApiDotNetCore.MongoDb.sln +++ b/JsonApiDotNetCore.MongoDb.sln @@ -23,11 +23,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig .gitignore = .gitignore + .github\workflows\build.yml = .github\workflows\build.yml CodingGuidelines.ruleset = CodingGuidelines.ruleset CSharpGuidelinesAnalyzer.config = CSharpGuidelinesAnalyzer.config Directory.Build.props = Directory.Build.props - tests.runsettings = tests.runsettings package-versions.props = package-versions.props + tests.runsettings = tests.runsettings EndProjectSection EndProject Global diff --git a/WarningSeverities.DotSettings b/WarningSeverities.DotSettings index 5c641e6..060df31 100644 --- a/WarningSeverities.DotSettings +++ b/WarningSeverities.DotSettings @@ -69,6 +69,7 @@ WARNING WARNING WARNING + WARNING WARNING WARNING WARNING @@ -122,6 +123,7 @@ WARNING WARNING WARNING + WARNING WARNING WARNING WARNING @@ -164,7 +166,6 @@ WARNING WARNING WARNING - WARNING WARNING WARNING WARNING @@ -196,6 +197,7 @@ WARNING WARNING WARNING + WARNING WARNING WARNING WARNING diff --git a/cleanupcode.ps1 b/cleanupcode.ps1 index a593bd9..9a86aba 100644 --- a/cleanupcode.ps1 +++ b/cleanupcode.ps1 @@ -28,17 +28,17 @@ if ($revision) { if ($baseCommitHash -eq $headCommitHash) { Write-Output "Running code cleanup on staged/unstaged files." - dotnet regitlint -s JsonApiDotNetCore.MongoDb.sln --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --verbosity=WARN -f staged,modified + dotnet regitlint -s JsonApiDotNetCore.MongoDb.sln --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN -f staged,modified VerifySuccessExitCode } else { Write-Output "Running code cleanup on commit range $baseCommitHash..$headCommitHash, including staged/unstaged files." - dotnet regitlint -s JsonApiDotNetCore.MongoDb.sln --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --verbosity=WARN -f staged,modified,commits -a $headCommitHash -b $baseCommitHash + dotnet regitlint -s JsonApiDotNetCore.MongoDb.sln --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN -f staged,modified,commits -a $headCommitHash -b $baseCommitHash VerifySuccessExitCode } } else { Write-Output "Running code cleanup on all files." - dotnet regitlint -s JsonApiDotNetCore.MongoDb.sln --print-command --skip-tool-check --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --verbosity=WARN + dotnet regitlint -s JsonApiDotNetCore.MongoDb.sln --print-command --skip-tool-check --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN VerifySuccessExitCode } diff --git a/logo.png b/logo.png deleted file mode 100644 index 78f1acd..0000000 Binary files a/logo.png and /dev/null differ diff --git a/package-icon.png b/package-icon.png new file mode 100644 index 0000000..f95eb77 Binary files /dev/null and b/package-icon.png differ diff --git a/package-versions.props b/package-versions.props index 6d226f5..cd63e0e 100644 --- a/package-versions.props +++ b/package-versions.props @@ -1,20 +1,20 @@ - 5.5.0 + 5.6.0 2.20.0 - 34.0.* + 35.5.* 6.0.* 1.1.* 6.12.* 2.3.* - 1.3.* - 2.22.* + 2.0.* + 2.27.* 8.0.* - 17.8.* - 2.5.* + 17.10.* + 2.8.* diff --git a/src/Examples/JsonApiDotNetCoreMongoDbExample/Controllers/OperationsController.cs b/src/Examples/JsonApiDotNetCoreMongoDbExample/Controllers/OperationsController.cs index 82f602d..b748e26 100644 --- a/src/Examples/JsonApiDotNetCoreMongoDbExample/Controllers/OperationsController.cs +++ b/src/Examples/JsonApiDotNetCoreMongoDbExample/Controllers/OperationsController.cs @@ -8,4 +8,5 @@ namespace JsonApiDotNetCoreMongoDbExample.Controllers; public sealed class OperationsController( IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, IOperationsProcessor processor, IJsonApiRequest request, - ITargetedFields targetedFields) : JsonApiOperationsController(options, resourceGraph, loggerFactory, processor, request, targetedFields); + ITargetedFields targetedFields, IAtomicOperationFilter operationFilter) : JsonApiOperationsController(options, resourceGraph, loggerFactory, processor, + request, targetedFields, operationFilter); diff --git a/src/JsonApiDotNetCore.MongoDb/AtomicOperations/MongoTransaction.cs b/src/JsonApiDotNetCore.MongoDb/AtomicOperations/MongoTransaction.cs index 3ea882d..3514e87 100644 --- a/src/JsonApiDotNetCore.MongoDb/AtomicOperations/MongoTransaction.cs +++ b/src/JsonApiDotNetCore.MongoDb/AtomicOperations/MongoTransaction.cs @@ -35,24 +35,20 @@ public Task AfterProcessOperationAsync(CancellationToken cancellationToken) } /// - public Task CommitAsync(CancellationToken cancellationToken) + public async Task CommitAsync(CancellationToken cancellationToken) { if (_ownsTransaction && _mongoDataAccess.ActiveSession != null) { - return _mongoDataAccess.ActiveSession.CommitTransactionAsync(cancellationToken); + await _mongoDataAccess.ActiveSession.CommitTransactionAsync(cancellationToken); } - - return Task.CompletedTask; } /// - public ValueTask DisposeAsync() + public async ValueTask DisposeAsync() { if (_ownsTransaction) { - return _mongoDataAccess.DisposeAsync(); + await _mongoDataAccess.DisposeAsync(); } - - return ValueTask.CompletedTask; } } diff --git a/src/JsonApiDotNetCore.MongoDb/Configuration/ResourceGraphExtensions.cs b/src/JsonApiDotNetCore.MongoDb/Configuration/ResourceGraphExtensions.cs new file mode 100644 index 0000000..af84a69 --- /dev/null +++ b/src/JsonApiDotNetCore.MongoDb/Configuration/ResourceGraphExtensions.cs @@ -0,0 +1,38 @@ +using System.Reflection; +using JsonApiDotNetCore.Configuration; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using MongoDB.Bson.Serialization.Attributes; + +namespace JsonApiDotNetCore.MongoDb.Configuration; + +internal static class ResourceGraphExtensions +{ + public static IReadOnlyModel ToEntityModel(this IResourceGraph resourceGraph) + { + var modelBuilder = new ModelBuilder(); + + foreach (ResourceType resourceType in resourceGraph.GetResourceTypes()) + { + IncludeResourceType(resourceType, modelBuilder); + } + + return modelBuilder.Model; + } + + private static void IncludeResourceType(ResourceType resourceType, ModelBuilder builder) + { + EntityTypeBuilder entityTypeBuilder = builder.Entity(resourceType.ClrType); + + foreach (PropertyInfo property in resourceType.ClrType.GetProperties().Where(property => !IsIgnored(property))) + { + entityTypeBuilder.Property(property.PropertyType, property.Name); + } + } + + private static bool IsIgnored(PropertyInfo property) + { + return property.GetCustomAttribute() != null; + } +} diff --git a/src/JsonApiDotNetCore.MongoDb/Configuration/ServiceCollectionExtensions.cs b/src/JsonApiDotNetCore.MongoDb/Configuration/ServiceCollectionExtensions.cs index d39c8c7..48278f0 100644 --- a/src/JsonApiDotNetCore.MongoDb/Configuration/ServiceCollectionExtensions.cs +++ b/src/JsonApiDotNetCore.MongoDb/Configuration/ServiceCollectionExtensions.cs @@ -1,5 +1,6 @@ using JetBrains.Annotations; using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.MongoDb.AtomicOperations; using JsonApiDotNetCore.MongoDb.Queries.Internal; using JsonApiDotNetCore.MongoDb.Repositories; @@ -17,6 +18,12 @@ public static class ServiceCollectionExtensions [PublicAPI] public static IServiceCollection AddJsonApiMongoDb(this IServiceCollection services) { + services.TryAddSingleton(serviceProvider => + { + var resourceGraph = serviceProvider.GetRequiredService(); + return resourceGraph.ToEntityModel(); + }); + services.TryAddScoped(); // Replace the built-in implementations from JsonApiDotNetCore. diff --git a/src/JsonApiDotNetCore.MongoDb/JsonApiDotNetCore.MongoDb.csproj b/src/JsonApiDotNetCore.MongoDb/JsonApiDotNetCore.MongoDb.csproj index 07d7077..354b32a 100644 --- a/src/JsonApiDotNetCore.MongoDb/JsonApiDotNetCore.MongoDb.csproj +++ b/src/JsonApiDotNetCore.MongoDb/JsonApiDotNetCore.MongoDb.csproj @@ -12,11 +12,11 @@ jsonapi;json:api;dotnet;asp.net;rest;web-api;MongoDB Persistence layer implementation for use of MongoDB in APIs using JsonApiDotNetCore. json-api-dotnet - https://github.com/json-api-dotnet/JsonApiDotNetCore.MongoDb + https://www.jsonapi.net/ MIT false See https://github.com/json-api-dotnet/JsonApiDotNetCore.MongoDb/releases. - logo.png + package-icon.png PackageReadme.md true true @@ -24,7 +24,7 @@ - + diff --git a/src/JsonApiDotNetCore.MongoDb/Repositories/IMongoDataAccess.cs b/src/JsonApiDotNetCore.MongoDb/Repositories/IMongoDataAccess.cs index ff2d348..c0f5852 100644 --- a/src/JsonApiDotNetCore.MongoDb/Repositories/IMongoDataAccess.cs +++ b/src/JsonApiDotNetCore.MongoDb/Repositories/IMongoDataAccess.cs @@ -1,3 +1,4 @@ +using Microsoft.EntityFrameworkCore.Metadata; using MongoDB.Driver; namespace JsonApiDotNetCore.MongoDb.Repositories; @@ -7,6 +8,11 @@ namespace JsonApiDotNetCore.MongoDb.Repositories; /// public interface IMongoDataAccess : IAsyncDisposable { + /// + /// Provides access to the entity model, which is built at startup. + /// + IReadOnlyModel EntityModel { get; } + /// /// Provides access to the underlying MongoDB database, which data changes can be applied on. /// diff --git a/src/JsonApiDotNetCore.MongoDb/Repositories/MongoDataAccess.cs b/src/JsonApiDotNetCore.MongoDb/Repositories/MongoDataAccess.cs index 8db3558..018b0a4 100644 --- a/src/JsonApiDotNetCore.MongoDb/Repositories/MongoDataAccess.cs +++ b/src/JsonApiDotNetCore.MongoDb/Repositories/MongoDataAccess.cs @@ -1,3 +1,4 @@ +using Microsoft.EntityFrameworkCore.Metadata; using MongoDB.Driver; namespace JsonApiDotNetCore.MongoDb.Repositories; @@ -5,6 +6,9 @@ namespace JsonApiDotNetCore.MongoDb.Repositories; /// public sealed class MongoDataAccess : IMongoDataAccess { + /// + public IReadOnlyModel EntityModel { get; } + /// public IMongoDatabase MongoDatabase { get; } @@ -14,10 +18,12 @@ public sealed class MongoDataAccess : IMongoDataAccess /// public string? TransactionId => ActiveSession is { IsInTransaction: true } ? ActiveSession.GetHashCode().ToString() : null; - public MongoDataAccess(IMongoDatabase mongoDatabase) + public MongoDataAccess(IReadOnlyModel entityModel, IMongoDatabase mongoDatabase) { + ArgumentGuard.NotNull(entityModel); ArgumentGuard.NotNull(mongoDatabase); + EntityModel = entityModel; MongoDatabase = mongoDatabase; } diff --git a/src/JsonApiDotNetCore.MongoDb/Repositories/MongoModel.cs b/src/JsonApiDotNetCore.MongoDb/Repositories/MongoModel.cs deleted file mode 100644 index 336a098..0000000 --- a/src/JsonApiDotNetCore.MongoDb/Repositories/MongoModel.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Reflection; -using JsonApiDotNetCore.Configuration; -using Microsoft.EntityFrameworkCore.Metadata; -using MongoDB.Bson.Serialization.Attributes; - -namespace JsonApiDotNetCore.MongoDb.Repositories; - -internal sealed class MongoModel : RuntimeModel -{ - public MongoModel(IResourceGraph resourceGraph) - { - ArgumentGuard.NotNull(resourceGraph); - - foreach (ResourceType resourceType in resourceGraph.GetResourceTypes()) - { - RuntimeEntityType entityType = AddEntityType(resourceType.ClrType.FullName!, resourceType.ClrType); - SetEntityProperties(entityType, resourceType); - } - } - - private static void SetEntityProperties(RuntimeEntityType entityType, ResourceType resourceType) - { - foreach (PropertyInfo property in resourceType.ClrType.GetProperties().Where(property => !IsIgnored(property))) - { - entityType.AddProperty(property.Name, property.PropertyType, property); - } - } - - private static bool IsIgnored(PropertyInfo property) - { - return property.GetCustomAttribute() != null; - } -} diff --git a/src/JsonApiDotNetCore.MongoDb/Repositories/MongoRepository.cs b/src/JsonApiDotNetCore.MongoDb/Repositories/MongoRepository.cs index c955f8c..579531c 100644 --- a/src/JsonApiDotNetCore.MongoDb/Repositories/MongoRepository.cs +++ b/src/JsonApiDotNetCore.MongoDb/Repositories/MongoRepository.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using System.Linq.Expressions; using JetBrains.Annotations; using JsonApiDotNetCore.Configuration; @@ -19,6 +20,12 @@ namespace JsonApiDotNetCore.MongoDb.Repositories; /// /// Implements the foundational Repository layer in the JsonApiDotNetCore architecture that uses MongoDB. /// +/// +/// The resource type. +/// +/// +/// The resource identifier type. +/// [PublicAPI] public class MongoRepository : IResourceRepository, IRepositorySupportsTransaction where TResource : class, IIdentifiable @@ -115,7 +122,7 @@ protected virtual IMongoQueryable ApplyQueryLayer(QueryLayer queryLay source = queryableHandler.Apply(source); } - var context = QueryableBuilderContext.CreateRoot(source, typeof(Queryable), new MongoModel(_resourceGraph), null); + var context = QueryableBuilderContext.CreateRoot(source, typeof(Queryable), _mongoDataAccess.EntityModel, null); Expression expression = _queryableBuilder.ApplyQuery(queryLayer, context); return (IMongoQueryable)source.Provider.CreateQuery(expression); @@ -150,7 +157,7 @@ private void AssertNoRelationshipsInSparseFieldSets() } /// - public virtual Task GetForCreateAsync(Type resourceClrType, TId id, CancellationToken cancellationToken) + public virtual Task GetForCreateAsync(Type resourceClrType, [DisallowNull] TId id, CancellationToken cancellationToken) { var resource = (TResource)_resourceFactory.CreateInstance(resourceClrType); resource.Id = id; @@ -174,9 +181,9 @@ public virtual async Task CreateAsync(TResource resourceFromRequest, TResource r await _resourceDefinitionAccessor.OnWritingAsync(resourceForDatabase, WriteOperationKind.CreateResource, cancellationToken); await SaveChangesAsync( - () => _mongoDataAccess.ActiveSession != null + async () => await (_mongoDataAccess.ActiveSession != null ? Collection.InsertOneAsync(_mongoDataAccess.ActiveSession, resourceForDatabase, cancellationToken: cancellationToken) - : Collection.InsertOneAsync(resourceForDatabase, cancellationToken: cancellationToken), cancellationToken); + : Collection.InsertOneAsync(resourceForDatabase, cancellationToken: cancellationToken)), cancellationToken); await _resourceDefinitionAccessor.OnWriteSucceededAsync(resourceForDatabase, WriteOperationKind.CreateResource, cancellationToken); } @@ -224,7 +231,7 @@ await SaveChangesAsync( } /// - public virtual async Task DeleteAsync(TResource? resourceFromDatabase, TId id, CancellationToken cancellationToken) + public virtual async Task DeleteAsync(TResource? resourceFromDatabase, [DisallowNull] TId id, CancellationToken cancellationToken) { TResource placeholderResource = resourceFromDatabase ?? _resourceFactory.CreateInstance(); placeholderResource.Id = id; @@ -259,7 +266,7 @@ public virtual Task SetRelationshipAsync(TResource leftResource, object? rightVa } /// - public virtual Task AddToToManyRelationshipAsync(TResource? leftResource, TId leftId, ISet rightResourceIds, + public virtual Task AddToToManyRelationshipAsync(TResource? leftResource, [DisallowNull] TId leftId, ISet rightResourceIds, CancellationToken cancellationToken) { throw new UnsupportedRelationshipException(); diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/AtomicOperationsFixture.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/AtomicOperationsFixture.cs index 21db655..262a2b6 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/AtomicOperationsFixture.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/AtomicOperationsFixture.cs @@ -32,8 +32,8 @@ public Task InitializeAsync() return Task.CompletedTask; } - public Task DisposeAsync() + public async Task DisposeAsync() { - return TestContext.DisposeAsync(); + await TestContext.DisposeAsync(); } } diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithClientGeneratedIdTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithClientGeneratedIdTests.cs index 27813bc..7fdf996 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithClientGeneratedIdTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithClientGeneratedIdTests.cs @@ -132,10 +132,10 @@ public async Task Cannot_create_resource_for_existing_client_generated_ID() string newIsoCode = _fakers.TextLanguage.Generate().IsoCode!; - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.TextLanguages.Add(existingLanguage); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToManyRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToManyRelationshipTests.cs index 7fa0e1c..70b5468 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToManyRelationshipTests.cs @@ -20,10 +20,10 @@ public async Task Cannot_create_ToMany_relationship() string newTitle = _fakers.MusicTrack.Generate().Title; - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.Performers.Add(existingPerformer); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToOneRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToOneRelationshipTests.cs index f33a634..51fd385 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToOneRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToOneRelationshipTests.cs @@ -20,10 +20,10 @@ public async Task Cannot_create_ToOne_relationship() string newLyricText = _fakers.Lyric.Generate().Text; - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.MusicTracks.Add(existingTrack); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Deleting/AtomicDeleteResourceTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Deleting/AtomicDeleteResourceTests.cs index 9e401bd..cd7accf 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Deleting/AtomicDeleteResourceTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Deleting/AtomicDeleteResourceTests.cs @@ -18,10 +18,10 @@ public async Task Can_delete_existing_resource() // Arrange Performer existingPerformer = _fakers.Performer.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.Performers.Add(existingPerformer); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Meta/AtomicResourceMetaTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Meta/AtomicResourceMetaTests.cs index ed87024..a701256 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Meta/AtomicResourceMetaTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Meta/AtomicResourceMetaTests.cs @@ -112,10 +112,10 @@ public async Task Returns_resource_meta_in_update_resource_with_side_effects() TextLanguage existingLanguage = _fakers.TextLanguage.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.TextLanguages.Add(existingLanguage); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/OperationsController.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/OperationsController.cs index c7ce7f9..d8ec189 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/OperationsController.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/OperationsController.cs @@ -9,4 +9,5 @@ namespace JsonApiDotNetCoreMongoDbTests.IntegrationTests.AtomicOperations; public sealed class OperationsController( IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, IOperationsProcessor processor, IJsonApiRequest request, - ITargetedFields targetedFields) : JsonApiOperationsController(options, resourceGraph, loggerFactory, processor, request, targetedFields); + ITargetedFields targetedFields, IAtomicOperationFilter operationFilter) : JsonApiOperationsController(options, resourceGraph, loggerFactory, processor, + request, targetedFields, operationFilter); diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/OperationsFakers.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/OperationsFakers.cs index 9804a9e..51f3ba8 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/OperationsFakers.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/OperationsFakers.cs @@ -7,7 +7,7 @@ namespace JsonApiDotNetCoreMongoDbTests.IntegrationTests.AtomicOperations; -internal sealed class OperationsFakers : FakerContainer +internal sealed class OperationsFakers { private static readonly Lazy> LazyLanguageIsoCodes = new(() => CultureInfo .GetCultures(CultureTypes.NeutralCultures) @@ -16,32 +16,32 @@ internal sealed class OperationsFakers : FakerContainer .ToArray()); private readonly Lazy> _lazyPlaylistFaker = new(() => new Faker() - .UseSeed(GetFakerSeed()) + .MakeDeterministic() .RuleFor(playlist => playlist.Name, faker => faker.Lorem.Sentence())); private readonly Lazy> _lazyMusicTrackFaker = new(() => new Faker() - .UseSeed(GetFakerSeed()) + .MakeDeterministic() .RuleFor(musicTrack => musicTrack.Title, faker => faker.Lorem.Word()) .RuleFor(musicTrack => musicTrack.LengthInSeconds, faker => faker.Random.Decimal(3 * 60, 5 * 60)) .RuleFor(musicTrack => musicTrack.Genre, faker => faker.Lorem.Word()) .RuleFor(musicTrack => musicTrack.ReleasedAt, faker => faker.Date.PastOffset().TruncateToWholeMilliseconds())); private readonly Lazy> _lazyLyricFaker = new(() => new Faker() - .UseSeed(GetFakerSeed()) + .MakeDeterministic() .RuleFor(lyric => lyric.Text, faker => faker.Lorem.Text()) .RuleFor(lyric => lyric.Format, "LRC")); private readonly Lazy> _lazyTextLanguageFaker = new(() => new Faker() - .UseSeed(GetFakerSeed()) + .MakeDeterministic() .RuleFor(textLanguage => textLanguage.IsoCode, faker => faker.PickRandom(LazyLanguageIsoCodes.Value))); private readonly Lazy> _lazyPerformerFaker = new(() => new Faker() - .UseSeed(GetFakerSeed()) + .MakeDeterministic() .RuleFor(performer => performer.ArtistName, faker => faker.Name.FullName()) .RuleFor(performer => performer.BornAt, faker => faker.Date.PastOffset().TruncateToWholeMilliseconds())); private readonly Lazy> _lazyRecordCompanyFaker = new(() => new Faker() - .UseSeed(GetFakerSeed()) + .MakeDeterministic() .RuleFor(recordCompany => recordCompany.Name, faker => faker.Company.CompanyName()) .RuleFor(recordCompany => recordCompany.CountryOfResidence, faker => faker.Address.Country())); diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/AtomicRollbackTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/AtomicRollbackTests.cs index 26ea797..0a2cc3a 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/AtomicRollbackTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/AtomicRollbackTests.cs @@ -26,7 +26,7 @@ public async Task Can_rollback_created_resource_on_error() string newArtistName = _fakers.Performer.Generate().ArtistName!; DateTimeOffset newBornAt = _fakers.Performer.Generate().BornAt; - await _testContext.RunOnDatabaseAsync(dbContext => dbContext.ClearTableAsync()); + await _testContext.RunOnDatabaseAsync(async dbContext => await dbContext.ClearTableAsync()); string unknownPerformerId = Unknown.StringId.For(); @@ -91,10 +91,10 @@ public async Task Can_rollback_updated_resource_on_error() string newArtistName = _fakers.Performer.Generate().ArtistName!; - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.Performers.Add(existingPerformer); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); string unknownPerformerId = Unknown.StringId.For(); diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/LyricRepository.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/LyricRepository.cs index d738e8d..d8ad7e0 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/LyricRepository.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/LyricRepository.cs @@ -20,14 +20,14 @@ public LyricRepository(IMongoDataAccess mongoDataAccess, ITargetedFields targete IEnumerable constraintProviders, IResourceDefinitionAccessor resourceDefinitionAccessor, IQueryableBuilder queryableBuilder) : base(mongoDataAccess, targetedFields, resourceGraph, resourceFactory, constraintProviders, resourceDefinitionAccessor, queryableBuilder) { - IMongoDataAccess otherDataAccess = new MongoDataAccess(mongoDataAccess.MongoDatabase); + IMongoDataAccess otherDataAccess = new MongoDataAccess(mongoDataAccess.EntityModel, mongoDataAccess.MongoDatabase); var factory = new MongoTransactionFactory(otherDataAccess); _transaction = factory.BeginTransactionAsync(CancellationToken.None).Result; } - public ValueTask DisposeAsync() + public async ValueTask DisposeAsync() { - return _transaction.DisposeAsync(); + await _transaction.DisposeAsync(); } } diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicAddToToManyRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicAddToToManyRelationshipTests.cs index b81b3f4..50382cb 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicAddToToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicAddToToManyRelationshipTests.cs @@ -19,11 +19,11 @@ public async Task Cannot_add_to_OneToMany_relationship() MusicTrack existingTrack = _fakers.MusicTrack.Generate(); Performer existingPerformer = _fakers.Performer.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.Performers.Add(existingPerformer); dbContext.MusicTracks.Add(existingTrack); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new @@ -76,11 +76,11 @@ public async Task Cannot_add_to_ManyToMany_relationship() Playlist existingPlaylist = _fakers.Playlist.Generate(); MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.MusicTracks.Add(existingTrack); dbContext.Playlists.Add(existingPlaylist); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicRemoveFromToManyRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicRemoveFromToManyRelationshipTests.cs index 71bfc3d..8ecb491 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicRemoveFromToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicRemoveFromToManyRelationshipTests.cs @@ -19,11 +19,11 @@ public async Task Cannot_remove_from_OneToMany_relationship() MusicTrack existingTrack = _fakers.MusicTrack.Generate(); existingTrack.Performers = _fakers.Performer.Generate(1); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.Performers.Add(existingTrack.Performers[0]); dbContext.MusicTracks.Add(existingTrack); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new @@ -76,11 +76,11 @@ public async Task Cannot_remove_from_ManyToMany_relationship() Playlist existingPlaylist = _fakers.Playlist.Generate(); existingPlaylist.Tracks = _fakers.MusicTrack.Generate(1); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.MusicTracks.Add(existingPlaylist.Tracks[0]); dbContext.Playlists.Add(existingPlaylist); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicReplaceToManyRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicReplaceToManyRelationshipTests.cs index 04c3bc3..09f2979 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicReplaceToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicReplaceToManyRelationshipTests.cs @@ -19,11 +19,11 @@ public async Task Cannot_replace_OneToMany_relationship() MusicTrack existingTrack = _fakers.MusicTrack.Generate(); Performer existingPerformer = _fakers.Performer.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.Performers.Add(existingPerformer); dbContext.MusicTracks.Add(existingTrack); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new @@ -76,11 +76,11 @@ public async Task Cannot_replace_ManyToMany_relationship() Playlist existingPlaylist = _fakers.Playlist.Generate(); MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.MusicTracks.Add(existingTrack); dbContext.Playlists.Add(existingPlaylist); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicUpdateToOneRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicUpdateToOneRelationshipTests.cs index bcbdcca..2541703 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicUpdateToOneRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicUpdateToOneRelationshipTests.cs @@ -19,11 +19,11 @@ public async Task Cannot_create_ManyToOne_relationship() MusicTrack existingTrack = _fakers.MusicTrack.Generate(); RecordCompany existingCompany = _fakers.RecordCompany.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.RecordCompanies.Add(existingCompany); dbContext.MusicTracks.Add(existingTrack); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicReplaceToManyRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicReplaceToManyRelationshipTests.cs index c65167b..329d74d 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicReplaceToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicReplaceToManyRelationshipTests.cs @@ -19,11 +19,11 @@ public async Task Cannot_replace_ToMany_relationship() MusicTrack existingTrack = _fakers.MusicTrack.Generate(); Performer existingPerformer = _fakers.Performer.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.Performers.Add(existingPerformer); dbContext.MusicTracks.Add(existingTrack); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateResourceTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateResourceTests.cs index a123409..9b88500 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateResourceTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateResourceTests.cs @@ -84,10 +84,10 @@ public async Task Can_update_resource_without_attributes_or_relationships() // Arrange MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.MusicTracks.Add(existingTrack); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new @@ -139,10 +139,10 @@ public async Task Can_partially_update_resource_without_side_effects() string newGenre = _fakers.MusicTrack.Generate().Genre!; - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.MusicTracks.Add(existingTrack); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new @@ -197,10 +197,10 @@ public async Task Can_completely_update_resource_without_side_effects() string newGenre = _fakers.MusicTrack.Generate().Genre!; DateTimeOffset newReleasedAt = _fakers.MusicTrack.Generate().ReleasedAt; - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.MusicTracks.Add(existingTrack); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new @@ -254,10 +254,10 @@ public async Task Can_update_resource_with_side_effects() TextLanguage existingLanguage = _fakers.TextLanguage.Generate(); string newIsoCode = _fakers.TextLanguage.Generate().IsoCode!; - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.TextLanguages.Add(existingLanguage); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateToOneRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateToOneRelationshipTests.cs index 014b396..75734f4 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateToOneRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateToOneRelationshipTests.cs @@ -19,11 +19,11 @@ public async Task Cannot_create_ToOne_relationship() Lyric existingLyric = _fakers.Lyric.Generate(); MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.MusicTracks.Add(existingTrack); dbContext.Lyrics.Add(existingLyric); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/Meta/MetaFakers.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/Meta/MetaFakers.cs index 5f29687..9b33ec2 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/Meta/MetaFakers.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/Meta/MetaFakers.cs @@ -6,10 +6,10 @@ namespace JsonApiDotNetCoreMongoDbTests.IntegrationTests.Meta; -internal sealed class MetaFakers : FakerContainer +internal sealed class MetaFakers { private readonly Lazy> _lazySupportTicketFaker = new(() => new Faker() - .UseSeed(GetFakerSeed()) + .MakeDeterministic() .RuleFor(supportTicket => supportTicket.Description, faker => faker.Lorem.Paragraph())); public Faker SupportTicket => _lazySupportTicketFaker.Value; diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/Meta/TopLevelCountTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/Meta/TopLevelCountTests.cs index cd122ae..13bb952 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/Meta/TopLevelCountTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/Meta/TopLevelCountTests.cs @@ -59,7 +59,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Renders_resource_count_for_empty_collection() { // Arrange - await _testContext.RunOnDatabaseAsync(dbContext => dbContext.ClearTableAsync()); + await _testContext.RunOnDatabaseAsync(async dbContext => await dbContext.ClearTableAsync()); const string route = "/supportTickets"; @@ -111,10 +111,10 @@ public async Task Hides_resource_count_in_update_resource_response() string newDescription = _fakers.SupportTicket.Generate().Description; - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.SupportTickets.Add(existingTicket); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/QueryStringFakers.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/QueryStringFakers.cs index 3026b37..84e1eee 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/QueryStringFakers.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/QueryStringFakers.cs @@ -6,20 +6,20 @@ namespace JsonApiDotNetCoreMongoDbTests.IntegrationTests.QueryStrings; -internal sealed class QueryStringFakers : FakerContainer +internal sealed class QueryStringFakers { private readonly Lazy> _lazyBlogFaker = new(() => new Faker() - .UseSeed(GetFakerSeed()) + .MakeDeterministic() .RuleFor(blog => blog.Title, faker => faker.Lorem.Word()) .RuleFor(blog => blog.PlatformName, faker => faker.Company.CompanyName())); private readonly Lazy> _lazyBlogPostFaker = new(() => new Faker() - .UseSeed(GetFakerSeed()) + .MakeDeterministic() .RuleFor(blogPost => blogPost.Caption, faker => faker.Lorem.Sentence()) .RuleFor(blogPost => blogPost.Url, faker => faker.Internet.Url())); private readonly Lazy> _lazyWebAccountFaker = new(() => new Faker() - .UseSeed(GetFakerSeed()) + .MakeDeterministic() .RuleFor(webAccount => webAccount.UserName, faker => faker.Person.UserName) .RuleFor(webAccount => webAccount.Password, faker => faker.Internet.Password()) .RuleFor(webAccount => webAccount.DisplayName, faker => faker.Person.FullName) diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/SparseFieldSets/SparseFieldSetTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/SparseFieldSets/SparseFieldSetTests.cs index b61ebac..8b94f13 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/SparseFieldSets/SparseFieldSetTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/SparseFieldSets/SparseFieldSetTests.cs @@ -120,10 +120,10 @@ public async Task Can_select_attribute_in_primary_resource_by_ID() BlogPost post = _fakers.BlogPost.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.Posts.Add(post); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); string route = $"/blogPosts/{post.StringId}?fields[blogPosts]=url"; @@ -151,10 +151,10 @@ public async Task Cannot_select_fields_of_ManyToOne_relationship() // Arrange BlogPost post = _fakers.BlogPost.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.Posts.Add(post); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); string route = $"/blogPosts/{post.StringId}?fields[webAccounts]=displayName,emailAddress,preferences"; @@ -180,10 +180,10 @@ public async Task Cannot_select_fields_of_OneToMany_relationship() // Arrange WebAccount account = _fakers.WebAccount.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.Accounts.Add(account); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); string route = $"/webAccounts/{account.StringId}?fields[blogPosts]=caption,labels"; @@ -209,10 +209,10 @@ public async Task Cannot_select_fields_of_ManyToMany_relationship() // Arrange BlogPost post = _fakers.BlogPost.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.Posts.Add(post); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); string route = $"/blogPosts/{post.StringId}?fields[labels]=color"; @@ -312,10 +312,10 @@ public async Task Fetches_all_scalar_properties_when_fieldset_contains_readonly_ Blog blog = _fakers.Blog.Generate(); blog.IsPublished = true; - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.Blogs.Add(blog); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); string route = $"/blogs/{blog.StringId}?fields[blogs]=showAdvertisements"; diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithClientGeneratedIdTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithClientGeneratedIdTests.cs index c763529..c9c732a 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithClientGeneratedIdTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithClientGeneratedIdTests.cs @@ -202,10 +202,10 @@ public async Task Cannot_create_resource_for_existing_client_generated_ID() string newDisplayName = _fakers.RgbColor.Generate().DisplayName; - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.RgbColors.Add(existingColor); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToManyRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToManyRelationshipTests.cs index f021d9b..e0d92de 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToManyRelationshipTests.cs @@ -26,10 +26,10 @@ public async Task Cannot_create_resource_with_ToMany_relationship() // Arrange UserAccount? existingUserAccount = _fakers.UserAccount.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.UserAccounts.Add(existingUserAccount); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToOneRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToOneRelationshipTests.cs index f02131d..be6732c 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToOneRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToOneRelationshipTests.cs @@ -29,11 +29,11 @@ public async Task Cannot_create_resource_with_ToOne_relationship() string newGroupName = _fakers.WorkItemGroup.Generate().Name; - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.RgbColors.Add(existingGroup.Color); dbContext.Groups.Add(existingGroup); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Deleting/DeleteResourceTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Deleting/DeleteResourceTests.cs index c00fd07..3e1bb87 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Deleting/DeleteResourceTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Deleting/DeleteResourceTests.cs @@ -26,10 +26,10 @@ public async Task Can_delete_existing_resource() // Arrange WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.WorkItems.Add(existingWorkItem); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); string route = $"/workItems/{existingWorkItem.StringId}"; diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Fetching/FetchRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Fetching/FetchRelationshipTests.cs index a7f74eb..6a9e32c 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Fetching/FetchRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Fetching/FetchRelationshipTests.cs @@ -26,10 +26,10 @@ public async Task Cannot_get_ManyToOne_relationship() { WorkItem workItem = _fakers.WorkItem.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.WorkItems.Add(workItem); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); string route = $"/workItems/{workItem.StringId}/relationships/assignee"; @@ -55,10 +55,10 @@ public async Task Cannot_get_OneToMany_relationship() // Arrange UserAccount userAccount = _fakers.UserAccount.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.UserAccounts.Add(userAccount); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); string route = $"/userAccounts/{userAccount.StringId}/relationships/assignedItems"; @@ -84,10 +84,10 @@ public async Task Cannot_get_ManyToMany_relationship() // Arrange WorkItem workItem = _fakers.WorkItem.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.WorkItems.Add(workItem); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); string route = $"/workItems/{workItem.StringId}/relationships/tags"; diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Fetching/FetchResourceTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Fetching/FetchResourceTests.cs index c8ff584..39a52d6 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Fetching/FetchResourceTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Fetching/FetchResourceTests.cs @@ -65,10 +65,10 @@ public async Task Can_get_primary_resource_by_ID() // Arrange WorkItem workItem = _fakers.WorkItem.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.WorkItems.Add(workItem); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); string route = $"/workItems/{workItem.StringId}"; @@ -116,10 +116,10 @@ public async Task Cannot_get_secondary_ManyToOne_resource() // Arrange WorkItem workItem = _fakers.WorkItem.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.WorkItems.Add(workItem); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); string route = $"/workItems/{workItem.StringId}/assignee"; @@ -145,10 +145,10 @@ public async Task Cannot_get_secondary_OneToMany_resources() // Arrange UserAccount userAccount = _fakers.UserAccount.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.UserAccounts.Add(userAccount); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); string route = $"/userAccounts/{userAccount.StringId}/assignedItems"; @@ -174,10 +174,10 @@ public async Task Cannot_get_secondary_ManyToMany_resources() // Arrange WorkItem workItem = _fakers.WorkItem.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.WorkItems.Add(workItem); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); string route = $"/workItems/{workItem.StringId}/tags"; diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/ImplicitlyChangingWorkItemDefinition.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/ImplicitlyChangingWorkItemDefinition.cs index 38b54cf..4c610bf 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/ImplicitlyChangingWorkItemDefinition.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/ImplicitlyChangingWorkItemDefinition.cs @@ -17,11 +17,11 @@ public sealed class ImplicitlyChangingWorkItemDefinition(IResourceGraph resource private readonly ReadWriteDbContext _dbContext = dbContext; - public override Task OnWriteSucceededAsync(WorkItem resource, WriteOperationKind writeOperation, CancellationToken cancellationToken) + public override async Task OnWriteSucceededAsync(WorkItem resource, WriteOperationKind writeOperation, CancellationToken cancellationToken) { if (writeOperation is not WriteOperationKind.DeleteResource) { - return _dbContext.WorkItems.ExecuteAsync(async collection => + await _dbContext.WorkItems.ExecuteAsync(async collection => { resource.Description += Suffix; @@ -29,7 +29,5 @@ public override Task OnWriteSucceededAsync(WorkItem resource, WriteOperationKind await collection.ReplaceOneAsync(filter, resource, cancellationToken: cancellationToken); }); } - - return Task.CompletedTask; } } diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/ImplicitlyChangingWorkItemGroupDefinition.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/ImplicitlyChangingWorkItemGroupDefinition.cs index ef8c375..570d745 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/ImplicitlyChangingWorkItemGroupDefinition.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/ImplicitlyChangingWorkItemGroupDefinition.cs @@ -17,11 +17,11 @@ public sealed class ImplicitlyChangingWorkItemGroupDefinition(IResourceGraph res private readonly ReadWriteDbContext _dbContext = dbContext; - public override Task OnWriteSucceededAsync(WorkItemGroup resource, WriteOperationKind writeOperation, CancellationToken cancellationToken) + public override async Task OnWriteSucceededAsync(WorkItemGroup resource, WriteOperationKind writeOperation, CancellationToken cancellationToken) { if (writeOperation is not WriteOperationKind.DeleteResource) { - return _dbContext.Groups.ExecuteAsync(async collection => + await _dbContext.Groups.ExecuteAsync(async collection => { resource.Name += Suffix; @@ -29,7 +29,5 @@ public override Task OnWriteSucceededAsync(WorkItemGroup resource, WriteOperatio await collection.ReplaceOneAsync(filter, resource, cancellationToken: cancellationToken); }); } - - return Task.CompletedTask; } } diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/ReadWriteFakers.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/ReadWriteFakers.cs index 504b9c3..0c84e48 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/ReadWriteFakers.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/ReadWriteFakers.cs @@ -7,31 +7,31 @@ namespace JsonApiDotNetCoreMongoDbTests.IntegrationTests.ReadWrite; -internal sealed class ReadWriteFakers : FakerContainer +internal sealed class ReadWriteFakers { private readonly Lazy> _lazyWorkItemFaker = new(() => new Faker() - .UseSeed(GetFakerSeed()) + .MakeDeterministic() .RuleFor(workItem => workItem.Description, faker => faker.Lorem.Sentence()) .RuleFor(workItem => workItem.DueAt, faker => faker.Date.Future().TruncateToWholeMilliseconds()) .RuleFor(workItem => workItem.Priority, faker => faker.PickRandom())); private readonly Lazy> _lazyWorkTagFaker = new(() => new Faker() - .UseSeed(GetFakerSeed()) + .MakeDeterministic() .RuleFor(workTag => workTag.Text, faker => faker.Lorem.Word()) .RuleFor(workTag => workTag.IsBuiltIn, faker => faker.Random.Bool())); private readonly Lazy> _lazyUserAccountFaker = new(() => new Faker() - .UseSeed(GetFakerSeed()) + .MakeDeterministic() .RuleFor(userAccount => userAccount.FirstName, faker => faker.Name.FirstName()) .RuleFor(userAccount => userAccount.LastName, faker => faker.Name.LastName())); private readonly Lazy> _lazyWorkItemGroupFaker = new(() => new Faker() - .UseSeed(GetFakerSeed()) + .MakeDeterministic() .RuleFor(group => group.Name, faker => faker.Lorem.Word()) .RuleFor(group => group.IsPublic, faker => faker.Random.Bool())); private readonly Lazy> _lazyRgbColorFaker = new(() => new Faker() - .UseSeed(GetFakerSeed()) + .MakeDeterministic() .RuleFor(color => color.Id, faker => ObjectId.GenerateNewId(faker.Date.Past()).ToString()) .RuleFor(color => color.DisplayName, faker => faker.Commerce.Color())); diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/AddToToManyRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/AddToToManyRelationshipTests.cs index 970c893..c2fd820 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/AddToToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/AddToToManyRelationshipTests.cs @@ -27,11 +27,11 @@ public async Task Cannot_add_to_OneToMany_relationship() WorkItem existingWorkItem = _fakers.WorkItem.Generate(); UserAccount existingSubscriber = _fakers.UserAccount.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.UserAccounts.Add(existingSubscriber); dbContext.WorkItems.Add(existingWorkItem); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new @@ -70,11 +70,11 @@ public async Task Cannot_add_to_ManyToMany_relationship() WorkItem existingWorkItem = _fakers.WorkItem.Generate(); WorkTag existingTag = _fakers.WorkTag.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.WorkTags.Add(existingTag); dbContext.WorkItems.Add(existingWorkItem); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/RemoveFromToManyRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/RemoveFromToManyRelationshipTests.cs index 22dd312..eab8111 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/RemoveFromToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/RemoveFromToManyRelationshipTests.cs @@ -27,11 +27,11 @@ public async Task Cannot_remove_from_OneToMany_relationship() WorkItem existingWorkItem = _fakers.WorkItem.Generate(); existingWorkItem.Subscribers = _fakers.UserAccount.Generate(1).ToHashSet(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.UserAccounts.Add(existingWorkItem.Subscribers.ElementAt(0)); dbContext.WorkItems.Add(existingWorkItem); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new @@ -70,11 +70,11 @@ public async Task Cannot_remove_from_ManyToMany_relationship() WorkItem existingWorkItem = _fakers.WorkItem.Generate(); existingWorkItem.Tags = _fakers.WorkTag.Generate(1).ToHashSet(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.WorkTags.Add(existingWorkItem.Tags.ElementAt(0)); dbContext.WorkItems.Add(existingWorkItem); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/ReplaceToManyRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/ReplaceToManyRelationshipTests.cs index 0d623d7..9df3deb 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/ReplaceToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/ReplaceToManyRelationshipTests.cs @@ -27,11 +27,11 @@ public async Task Cannot_replace_OneToMany_relationship() WorkItem existingWorkItem = _fakers.WorkItem.Generate(); UserAccount existingSubscriber = _fakers.UserAccount.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.UserAccounts.Add(existingSubscriber); dbContext.WorkItems.Add(existingWorkItem); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new @@ -70,11 +70,11 @@ public async Task Cannot_replace_ManyToMany_relationship() WorkItem existingWorkItem = _fakers.WorkItem.Generate(); WorkTag existingTag = _fakers.WorkTag.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.WorkTags.Add(existingTag); dbContext.WorkItems.Add(existingWorkItem); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/UpdateToOneRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/UpdateToOneRelationshipTests.cs index 38168eb..ddd0f1d 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/UpdateToOneRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/UpdateToOneRelationshipTests.cs @@ -27,11 +27,11 @@ public async Task Cannot_replace_ToOne_relationship() WorkItemGroup existingGroup = _fakers.WorkItemGroup.Generate(); RgbColor existingColor = _fakers.RgbColor.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.RgbColors.Add(existingColor); dbContext.Groups.Add(existingGroup); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Resources/ReplaceToManyRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Resources/ReplaceToManyRelationshipTests.cs index fe61fa8..f7fa710 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Resources/ReplaceToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Resources/ReplaceToManyRelationshipTests.cs @@ -27,11 +27,11 @@ public async Task Cannot_replace_OneToMany_relationship() WorkItem existingWorkItem = _fakers.WorkItem.Generate(); UserAccount existingSubscriber = _fakers.UserAccount.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.UserAccounts.Add(existingSubscriber); dbContext.WorkItems.Add(existingWorkItem); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new @@ -81,11 +81,11 @@ public async Task Cannot_replace_ManyToMany_relationship() WorkItem existingWorkItem = _fakers.WorkItem.Generate(); WorkTag existingTag = _fakers.WorkTag.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.WorkTags.Add(existingTag); dbContext.WorkItems.Add(existingWorkItem); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateResourceTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateResourceTests.cs index 6163c5e..672b836 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateResourceTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateResourceTests.cs @@ -36,10 +36,10 @@ public async Task Can_update_resource_without_attributes_or_relationships() // Arrange UserAccount existingUserAccount = _fakers.UserAccount.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.UserAccounts.Add(existingUserAccount); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new @@ -83,10 +83,10 @@ public async Task Can_partially_update_resource_with_string_ID() WorkItemGroup existingGroup = _fakers.WorkItemGroup.Generate(); string newName = _fakers.WorkItemGroup.Generate().Name; - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.Groups.Add(existingGroup); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new @@ -135,10 +135,10 @@ public async Task Can_completely_update_resource_with_string_ID() RgbColor existingColor = _fakers.RgbColor.Generate(); string newDisplayName = _fakers.RgbColor.Generate().DisplayName; - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.RgbColors.Add(existingColor); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new @@ -179,10 +179,10 @@ public async Task Can_update_resource_without_side_effects() UserAccount existingUserAccount = _fakers.UserAccount.Generate(); UserAccount newUserAccount = _fakers.UserAccount.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.UserAccounts.Add(existingUserAccount); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new @@ -225,10 +225,10 @@ public async Task Can_update_resource_with_side_effects() WorkItem existingWorkItem = _fakers.WorkItem.Generate(); string newDescription = _fakers.WorkItem.Generate().Description!; - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.WorkItems.Add(existingWorkItem); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new @@ -281,10 +281,10 @@ public async Task Can_update_resource_with_side_effects_with_primary_fieldset() WorkItem existingWorkItem = _fakers.WorkItem.Generate(); string newDescription = _fakers.WorkItem.Generate().Description!; - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.WorkItems.Add(existingWorkItem); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateToOneRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateToOneRelationshipTests.cs index de4ddbc..c1e99fc 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateToOneRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateToOneRelationshipTests.cs @@ -27,11 +27,11 @@ public async Task Cannot_create_ToOne_relationship() WorkItemGroup existingGroup = _fakers.WorkItemGroup.Generate(); RgbColor existingColor = _fakers.RgbColor.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.RgbColors.Add(existingColor); dbContext.Groups.Add(existingGroup); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ResourceDefinitions/Reading/MoonDefinition.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ResourceDefinitions/Reading/MoonDefinition.cs index e4e8f7a..206db10 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ResourceDefinitions/Reading/MoonDefinition.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ResourceDefinitions/Reading/MoonDefinition.cs @@ -23,8 +23,6 @@ public override QueryStringParameterHandlers OnRegisterQueryableHandlersFo private static IQueryable FilterByRadius(IQueryable source, StringValues parameterValue) { - // Workaround for https://youtrack.jetbrains.com/issue/RSRP-493256/Incorrect-possible-null-assignment - // ReSharper disable once AssignNullToNotNullAttribute bool isFilterOnLargerThan = bool.Parse(parameterValue.ToString()); return isFilterOnLargerThan ? source.Where(moon => moon.SolarRadius > 1m) : source.Where(moon => moon.SolarRadius <= 1m); } diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ResourceDefinitions/Reading/ResourceDefinitionReadTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ResourceDefinitions/Reading/ResourceDefinitionReadTests.cs index 69bc808..df3364e 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ResourceDefinitions/Reading/ResourceDefinitionReadTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ResourceDefinitions/Reading/ResourceDefinitionReadTests.cs @@ -300,10 +300,10 @@ public async Task Attribute_inclusion_from_resource_definition_is_applied_for_om Star star = _fakers.Star.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.Stars.Add(star); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); string route = $"/stars/{star.StringId}"; @@ -340,10 +340,10 @@ public async Task Attribute_inclusion_from_resource_definition_is_applied_for_fi Star star = _fakers.Star.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.Stars.Add(star); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); string route = $"/stars/{star.StringId}?fields[stars]=name,solarRadius"; @@ -381,10 +381,10 @@ public async Task Attribute_exclusion_from_resource_definition_is_applied_for_om Star star = _fakers.Star.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.Stars.Add(star); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); string route = $"/stars/{star.StringId}"; @@ -421,10 +421,10 @@ public async Task Attribute_exclusion_from_resource_definition_is_applied_for_fi Star star = _fakers.Star.Generate(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.Stars.Add(star); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); string route = $"/stars/{star.StringId}?fields[stars]=name,isVisibleFromEarth"; @@ -558,10 +558,10 @@ public async Task Queryable_parameter_handler_from_resource_definition_is_not_ap Planet planet = _fakers.Planet.Generate(); planet.Moons = _fakers.Moon.Generate(1).ToHashSet(); - await _testContext.RunOnDatabaseAsync(dbContext => + await _testContext.RunOnDatabaseAsync(async dbContext => { dbContext.Planets.Add(planet); - return dbContext.SaveChangesAsync(); + await dbContext.SaveChangesAsync(); }); string route = $"/planets/{planet.StringId}/moons?isLargerThanTheSun=false"; diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ResourceDefinitions/Reading/UniverseFakers.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ResourceDefinitions/Reading/UniverseFakers.cs index 61164d4..7684481 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ResourceDefinitions/Reading/UniverseFakers.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ResourceDefinitions/Reading/UniverseFakers.cs @@ -6,10 +6,10 @@ namespace JsonApiDotNetCoreMongoDbTests.IntegrationTests.ResourceDefinitions.Reading; -internal sealed class UniverseFakers : FakerContainer +internal sealed class UniverseFakers { private readonly Lazy> _lazyStarFaker = new(() => new Faker() - .UseSeed(GetFakerSeed()) + .MakeDeterministic() .RuleFor(star => star.Name, faker => faker.Random.Word()) .RuleFor(star => star.Kind, faker => faker.PickRandom()) .RuleFor(star => star.SolarRadius, faker => faker.Random.Decimal(.01M, 1000M)) @@ -17,13 +17,13 @@ internal sealed class UniverseFakers : FakerContainer .RuleFor(star => star.IsVisibleFromEarth, faker => faker.Random.Bool())); private readonly Lazy> _lazyPlanetFaker = new(() => new Faker() - .UseSeed(GetFakerSeed()) + .MakeDeterministic() .RuleFor(planet => planet.PublicName, faker => faker.Random.Word()) .RuleFor(planet => planet.HasRingSystem, faker => faker.Random.Bool()) .RuleFor(planet => planet.SolarMass, faker => faker.Random.Decimal(.001M, 100M))); private readonly Lazy> _lazyMoonFaker = new(() => new Faker() - .UseSeed(GetFakerSeed()) + .MakeDeterministic() .RuleFor(moon => moon.Name, faker => faker.Random.Word()) .RuleFor(moon => moon.SolarRadius, faker => faker.Random.Decimal(.01M, 1000M))); diff --git a/test/TestBuildingBlocks/FakerContainer.cs b/test/TestBuildingBlocks/FakerExtensions.cs similarity index 86% rename from test/TestBuildingBlocks/FakerContainer.cs rename to test/TestBuildingBlocks/FakerExtensions.cs index 72f9a05..aff1cd0 100644 --- a/test/TestBuildingBlocks/FakerContainer.cs +++ b/test/TestBuildingBlocks/FakerExtensions.cs @@ -1,21 +1,27 @@ using System.Diagnostics; using System.Reflection; -using Bogus.DataSets; +using Bogus; using FluentAssertions.Extensions; using Xunit; namespace TestBuildingBlocks; -public abstract class FakerContainer +public static class FakerExtensions { - static FakerContainer() + public static Faker MakeDeterministic(this Faker faker) + where T : class { + int seed = GetFakerSeed(); + faker.UseSeed(seed); + // Setting the system DateTime to kind Utc, so that faker calls like PastOffset() don't depend on the system time zone. // See https://docs.microsoft.com/en-us/dotnet/api/system.datetimeoffset.op_implicit?view=net-6.0#remarks - Date.SystemClock = () => 1.January(2020).At(1, 1, 1).AsUtc(); + faker.UseDateTimeReference(1.January(2020).At(1, 1, 1).AsUtc()); + + return faker; } - protected static int GetFakerSeed() + private static int GetFakerSeed() { // The goal here is to have stable data over multiple test runs, but at the same time different data per test case. @@ -34,7 +40,7 @@ private static MethodBase GetTestMethod() if (testMethod == null) { // If called after the first await statement, the test method is no longer on the stack, - // but has been replaced with the compiler-generated async/wait state machine. + // but has been replaced with the compiler-generated async/await state machine. throw new InvalidOperationException("Fakers can only be used from within (the start of) a test method."); } diff --git a/test/TestBuildingBlocks/IntegrationTest.cs b/test/TestBuildingBlocks/IntegrationTest.cs index 2080a47..50fc3fd 100644 --- a/test/TestBuildingBlocks/IntegrationTest.cs +++ b/test/TestBuildingBlocks/IntegrationTest.cs @@ -22,34 +22,34 @@ static IntegrationTest() ThrottleSemaphore = new SemaphoreSlim(maxConcurrentTestRuns); } - public Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecuteGetAsync(string requestUrl, + public async Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecuteGetAsync(string requestUrl, Action? setRequestHeaders = null) { - return ExecuteRequestAsync(HttpMethod.Get, requestUrl, null, null, setRequestHeaders); + return await ExecuteRequestAsync(HttpMethod.Get, requestUrl, null, null, setRequestHeaders); } - public Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecutePostAsync(string requestUrl, + public async Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecutePostAsync(string requestUrl, object requestBody, string contentType = HeaderConstants.MediaType, Action? setRequestHeaders = null) { - return ExecuteRequestAsync(HttpMethod.Post, requestUrl, requestBody, contentType, setRequestHeaders); + return await ExecuteRequestAsync(HttpMethod.Post, requestUrl, requestBody, contentType, setRequestHeaders); } - public Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecutePostAtomicAsync(string requestUrl, + public async Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecutePostAtomicAsync(string requestUrl, object requestBody, string contentType = HeaderConstants.AtomicOperationsMediaType, Action? setRequestHeaders = null) { - return ExecuteRequestAsync(HttpMethod.Post, requestUrl, requestBody, contentType, setRequestHeaders); + return await ExecuteRequestAsync(HttpMethod.Post, requestUrl, requestBody, contentType, setRequestHeaders); } - public Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecutePatchAsync(string requestUrl, + public async Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecutePatchAsync(string requestUrl, object requestBody, string contentType = HeaderConstants.MediaType, Action? setRequestHeaders = null) { - return ExecuteRequestAsync(HttpMethod.Patch, requestUrl, requestBody, contentType, setRequestHeaders); + return await ExecuteRequestAsync(HttpMethod.Patch, requestUrl, requestBody, contentType, setRequestHeaders); } - public Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecuteDeleteAsync(string requestUrl, + public async Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecuteDeleteAsync(string requestUrl, object? requestBody = null, string contentType = HeaderConstants.MediaType, Action? setRequestHeaders = null) { - return ExecuteRequestAsync(HttpMethod.Delete, requestUrl, requestBody, contentType, setRequestHeaders); + return await ExecuteRequestAsync(HttpMethod.Delete, requestUrl, requestBody, contentType, setRequestHeaders); } private async Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecuteRequestAsync(HttpMethod method, @@ -110,9 +110,9 @@ static IntegrationTest() } } - public Task InitializeAsync() + public async Task InitializeAsync() { - return ThrottleSemaphore.WaitAsync(); + await ThrottleSemaphore.WaitAsync(); } public virtual Task DisposeAsync() diff --git a/test/TestBuildingBlocks/MongoDbContextShim.cs b/test/TestBuildingBlocks/MongoDbContextShim.cs index abc8942..82356d8 100644 --- a/test/TestBuildingBlocks/MongoDbContextShim.cs +++ b/test/TestBuildingBlocks/MongoDbContextShim.cs @@ -22,10 +22,10 @@ protected MongoDbSetShim Set() return dbSetShim; } - public Task ClearTableAsync() + public async Task ClearTableAsync() where TEntity : IMongoIdentifiable { - return _database.DropCollectionAsync(typeof(TEntity).Name); + await _database.DropCollectionAsync(typeof(TEntity).Name); } public async Task SaveChangesAsync(CancellationToken cancellation = default) diff --git a/test/TestBuildingBlocks/MongoDbSetShim.cs b/test/TestBuildingBlocks/MongoDbSetShim.cs index 16e35d5..182ac6e 100644 --- a/test/TestBuildingBlocks/MongoDbSetShim.cs +++ b/test/TestBuildingBlocks/MongoDbSetShim.cs @@ -57,9 +57,9 @@ internal override async Task PersistAsync(CancellationToken cancellationToken) } } - public Task ExecuteAsync(Func, Task> action) + public async Task ExecuteAsync(Func, Task> action) { - return action(_collection); + await action(_collection); } public async Task FirstWithIdAsync(string? id, CancellationToken cancellationToken = default) @@ -79,13 +79,13 @@ public async Task FirstWithIdAsync(string? id, CancellationToken cancel return await _collection.AsQueryable().FirstOrDefaultAsync(document => Equals(document.Id, id), cancellationToken); } - public Task> ToListAsync(CancellationToken cancellationToken = default) + public async Task> ToListAsync(CancellationToken cancellationToken = default) { - return _collection.AsQueryable().ToListAsync(cancellationToken); + return await _collection.AsQueryable().ToListAsync(cancellationToken); } - public Task> ToListWhereAsync(Expression> predicate, CancellationToken cancellationToken = default) + public async Task> ToListWhereAsync(Expression> predicate, CancellationToken cancellationToken = default) { - return _collection.AsQueryable().Where(predicate).ToListAsync(cancellationToken); + return await _collection.AsQueryable().Where(predicate).ToListAsync(cancellationToken); } }