diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index d914fc369d..f8589a73a7 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -3,13 +3,13 @@
"isRoot": true,
"tools": {
"jetbrains.resharper.globaltools": {
- "version": "2022.2.3",
+ "version": "2022.2.4",
"commands": [
"jb"
]
},
"regitlint": {
- "version": "6.1.1",
+ "version": "6.2.1",
"commands": [
"regitlint"
]
@@ -21,7 +21,7 @@
]
},
"dotnet-reportgenerator-globaltool": {
- "version": "5.1.3",
+ "version": "5.1.11",
"commands": [
"reportgenerator"
]
diff --git a/Build.ps1 b/Build.ps1
index d8be7da5e6..9b076bc4d8 100644
--- a/Build.ps1
+++ b/Build.ps1
@@ -51,7 +51,7 @@ function RunCleanupCode {
if ($baseCommitHash -ne $headCommitHash) {
Write-Output "Running code cleanup on commit range $baseCommitHash..$headCommitHash in pull request."
- dotnet regitlint -s JsonApiDotNetCore.sln --print-command --skip-tool-check --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.sln --print-command --skip-tool-check --max-runs=5 --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --verbosity=WARN -f commits -a $headCommitHash -b $baseCommitHash --fail-on-diff --print-diff
CheckLastExitCode
}
}
@@ -105,7 +105,7 @@ dotnet build -c Release
CheckLastExitCode
# https://youtrack.jetbrains.com/issue/RSRP-488628/Breaking-InspectCode-fails-with-Roslyn-Worker-process-exited-unexpectedly-after-update
-if ($env:APPVEYOR_BUILD_WORKER_IMAGE -ne 'Ubuntu') {
+if ($IsWindows) {
RunInspectCode
RunCleanupCode
}
diff --git a/Directory.Build.props b/Directory.Build.props
index 99319a64e6..1810b9cd46 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -6,7 +6,7 @@
6.0.*
4.3.*
2.14.1
- 5.1.0
+ 5.1.1
$(MSBuildThisFileDirectory)CodingGuidelines.ruleset
9999
enable
@@ -16,7 +16,7 @@
-
+
@@ -33,8 +33,8 @@
- 3.1.2
+ 3.2.0
4.18.2
- 17.3.1
+ 17.4.0
diff --git a/appveyor.yml b/appveyor.yml
index 61feec2ab8..81ba53020c 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,10 +1,10 @@
image:
- - Ubuntu
+ - Ubuntu2004
- Visual Studio 2022
version: '{build}'
-stack: postgresql 13.4
+stack: postgresql 15
environment:
PGUSER: postgres
@@ -34,7 +34,10 @@ for:
only:
- image: Visual Studio 2022
services:
- - postgresql13
+ - postgresql15
+ install:
+ # Temporary workaround for https://help.appveyor.com/discussions/questions/60488-postgresql-version
+ - net start postgresql-x64-15
# REF: https://github.com/docascode/docfx-seed/blob/master/appveyor.yml
before_build:
- pwsh: |
@@ -101,7 +104,7 @@ build_script:
Write-Output "PostgreSQL version:"
if ($IsWindows) {
- . "${env:ProgramFiles}\PostgreSQL\13\bin\psql" --version
+ . "${env:ProgramFiles}\PostgreSQL\15\bin\psql" --version
}
else {
psql --version
diff --git a/cleanupcode.ps1 b/cleanupcode.ps1
index bab8b82af1..5740ab5a90 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.sln --print-command --skip-tool-check --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --verbosity=WARN -f staged,modified
+ dotnet regitlint -s JsonApiDotNetCore.sln --print-command --skip-tool-check --max-runs=5 --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --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.sln --print-command --skip-tool-check --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --verbosity=WARN -f staged,modified,commits -a $headCommitHash -b $baseCommitHash
+ dotnet regitlint -s JsonApiDotNetCore.sln --print-command --skip-tool-check --max-runs=5 --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --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.sln --print-command --skip-tool-check --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --verbosity=WARN
+ dotnet regitlint -s JsonApiDotNetCore.sln --print-command --skip-tool-check --max-runs=5 --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --verbosity=WARN
VerifySuccessExitCode
}
diff --git a/docs/usage/reading/filtering.md b/docs/usage/reading/filtering.md
index a1c1215ccd..b99a14c3b2 100644
--- a/docs/usage/reading/filtering.md
+++ b/docs/usage/reading/filtering.md
@@ -196,7 +196,7 @@ matchTextExpression:
( 'contains' | 'startsWith' | 'endsWith' ) LPAREN fieldChain COMMA literalConstant RPAREN;
anyExpression:
- 'any' LPAREN fieldChain COMMA literalConstant ( COMMA literalConstant )+ RPAREN;
+ 'any' LPAREN fieldChain ( COMMA literalConstant )+ RPAREN;
hasExpression:
'has' LPAREN fieldChain ( COMMA filterExpression )? RPAREN;
diff --git a/run-docker-postgres.ps1 b/run-docker-postgres.ps1
index 89a325e3b5..153b93a846 100644
--- a/run-docker-postgres.ps1
+++ b/run-docker-postgres.ps1
@@ -9,4 +9,4 @@ docker run --rm --name jsonapi-dotnet-core-testing `
-e POSTGRES_USER=postgres `
-e POSTGRES_PASSWORD=postgres `
-p 5432:5432 `
- postgres:13.4
+ postgres:15
diff --git a/src/Examples/DatabasePerTenantExample/Data/AppDbContext.cs b/src/Examples/DatabasePerTenantExample/Data/AppDbContext.cs
index c70fc8655f..ba73b8bf3a 100644
--- a/src/Examples/DatabasePerTenantExample/Data/AppDbContext.cs
+++ b/src/Examples/DatabasePerTenantExample/Data/AppDbContext.cs
@@ -36,7 +36,7 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
private string GetConnectionString()
{
string? tenantName = GetTenantName();
- string connectionString = _configuration[$"Data:{tenantName ?? "Default"}Connection"];
+ string? connectionString = _configuration[$"Data:{tenantName ?? "Default"}Connection"];
if (connectionString == null)
{
diff --git a/src/Examples/NoEntityFrameworkExample/Services/WorkItemService.cs b/src/Examples/NoEntityFrameworkExample/Services/WorkItemService.cs
index 6df109e5ba..34a40755cb 100644
--- a/src/Examples/NoEntityFrameworkExample/Services/WorkItemService.cs
+++ b/src/Examples/NoEntityFrameworkExample/Services/WorkItemService.cs
@@ -11,12 +11,12 @@ namespace NoEntityFrameworkExample.Services;
[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)]
public sealed class WorkItemService : IResourceService
{
- private readonly string _connectionString;
+ private readonly string? _connectionString;
public WorkItemService(IConfiguration configuration)
{
string postgresPassword = Environment.GetEnvironmentVariable("PGPASSWORD") ?? "postgres";
- _connectionString = configuration["Data:DefaultConnection"].Replace("###", postgresPassword);
+ _connectionString = configuration["Data:DefaultConnection"]?.Replace("###", postgresPassword);
}
public async Task> GetAsync(CancellationToken cancellationToken)
diff --git a/src/JsonApiDotNetCore/CollectionExtensions.cs b/src/JsonApiDotNetCore/CollectionExtensions.cs
index 133231eb23..6a17fed7b9 100644
--- a/src/JsonApiDotNetCore/CollectionExtensions.cs
+++ b/src/JsonApiDotNetCore/CollectionExtensions.cs
@@ -79,15 +79,4 @@ public static IEnumerable WhereNotNull(this IEnumerable source)
return source.Where(element => element is not null)!;
#pragma warning restore AV1250 // Evaluate LINQ query before returning it
}
-
- public static void AddRange(this ICollection source, IEnumerable itemsToAdd)
- {
- ArgumentGuard.NotNull(source);
- ArgumentGuard.NotNull(itemsToAdd);
-
- foreach (T item in itemsToAdd)
- {
- source.Add(item);
- }
- }
}
diff --git a/src/JsonApiDotNetCore/Queries/Expressions/AnyExpression.cs b/src/JsonApiDotNetCore/Queries/Expressions/AnyExpression.cs
index 2b855b1bdb..ecacc41c7c 100644
--- a/src/JsonApiDotNetCore/Queries/Expressions/AnyExpression.cs
+++ b/src/JsonApiDotNetCore/Queries/Expressions/AnyExpression.cs
@@ -17,12 +17,7 @@ public class AnyExpression : FilterExpression
public AnyExpression(ResourceFieldChainExpression targetAttribute, IImmutableSet constants)
{
ArgumentGuard.NotNull(targetAttribute);
- ArgumentGuard.NotNull(constants);
-
- if (constants.Count < 2)
- {
- throw new ArgumentException("At least two constants are required.", nameof(constants));
- }
+ ArgumentGuard.NotNullNorEmpty(constants);
TargetAttribute = targetAttribute;
Constants = constants;
diff --git a/src/JsonApiDotNetCore/Queries/Internal/Parsing/FilterParser.cs b/src/JsonApiDotNetCore/Queries/Internal/Parsing/FilterParser.cs
index c68e0f77f7..b768eb15b1 100644
--- a/src/JsonApiDotNetCore/Queries/Internal/Parsing/FilterParser.cs
+++ b/src/JsonApiDotNetCore/Queries/Internal/Parsing/FilterParser.cs
@@ -199,11 +199,6 @@ protected AnyExpression ParseAny()
LiteralConstantExpression constant = ParseConstant();
constantsBuilder.Add(constant);
- EatSingleCharacterToken(TokenKind.Comma);
-
- constant = ParseConstant();
- constantsBuilder.Add(constant);
-
while (TokenStack.TryPeek(out Token? nextToken) && nextToken.Kind == TokenKind.Comma)
{
EatSingleCharacterToken(TokenKind.Comma);
diff --git a/src/JsonApiDotNetCore/Queries/Internal/Parsing/IncludeParser.cs b/src/JsonApiDotNetCore/Queries/Internal/Parsing/IncludeParser.cs
index 3c8be88e46..1250e36312 100644
--- a/src/JsonApiDotNetCore/Queries/Internal/Parsing/IncludeParser.cs
+++ b/src/JsonApiDotNetCore/Queries/Internal/Parsing/IncludeParser.cs
@@ -110,7 +110,7 @@ private ICollection LookupRelationshipName(string relationshipN
if (relationships.Any())
{
- relationshipsFound.AddRange(relationships);
+ relationshipsFound.UnionWith(relationships);
RelationshipAttribute[] relationshipsToInclude = relationships.Where(relationship => !relationship.IsIncludeBlocked()).ToArray();
ICollection affectedChildren = parent.EnsureChildren(relationshipsToInclude);
diff --git a/src/JsonApiDotNetCore/Queries/Internal/QueryLayerComposer.cs b/src/JsonApiDotNetCore/Queries/Internal/QueryLayerComposer.cs
index 29e0935954..4661a5bdda 100644
--- a/src/JsonApiDotNetCore/Queries/Internal/QueryLayerComposer.cs
+++ b/src/JsonApiDotNetCore/Queries/Internal/QueryLayerComposer.cs
@@ -254,7 +254,7 @@ private static IImmutableSet ApplyIncludeElementUpdate
IDictionary> updatesInChildren)
{
ImmutableHashSet.Builder newElementsBuilder = ImmutableHashSet.CreateBuilder();
- newElementsBuilder.AddRange(includeElements);
+ newElementsBuilder.UnionWith(includeElements);
foreach ((IncludeElementExpression existingElement, IImmutableSet updatedChildren) in updatesInChildren)
{
diff --git a/src/JsonApiDotNetCore/QueryStrings/Internal/FilterQueryStringParameterReader.cs b/src/JsonApiDotNetCore/QueryStrings/Internal/FilterQueryStringParameterReader.cs
index 60c7f6b75c..dace5b8ca4 100644
--- a/src/JsonApiDotNetCore/QueryStrings/Internal/FilterQueryStringParameterReader.cs
+++ b/src/JsonApiDotNetCore/QueryStrings/Internal/FilterQueryStringParameterReader.cs
@@ -77,18 +77,21 @@ public virtual void Read(string parameterName, StringValues parameterValue)
}
}
- private IEnumerable ExtractParameterValue(string parameterValue)
+ private IEnumerable ExtractParameterValue(string? parameterValue)
{
- if (_options.EnableLegacyFilterNotation)
+ if (parameterValue != null)
{
- foreach (string condition in LegacyConverter.ExtractConditions(parameterValue))
+ if (_options.EnableLegacyFilterNotation)
{
- yield return condition;
+ foreach (string condition in LegacyConverter.ExtractConditions(parameterValue))
+ {
+ yield return condition;
+ }
+ }
+ else
+ {
+ yield return parameterValue;
}
- }
- else
- {
- yield return parameterValue;
}
}
diff --git a/src/JsonApiDotNetCore/QueryStrings/Internal/IncludeQueryStringParameterReader.cs b/src/JsonApiDotNetCore/QueryStrings/Internal/IncludeQueryStringParameterReader.cs
index a4db6ebd4a..7db9a9a7d7 100644
--- a/src/JsonApiDotNetCore/QueryStrings/Internal/IncludeQueryStringParameterReader.cs
+++ b/src/JsonApiDotNetCore/QueryStrings/Internal/IncludeQueryStringParameterReader.cs
@@ -48,7 +48,7 @@ public virtual void Read(string parameterName, StringValues parameterValue)
{
try
{
- _includeExpression = GetInclude(parameterValue);
+ _includeExpression = GetInclude(parameterValue.ToString());
}
catch (QueryParseException exception)
{
diff --git a/src/JsonApiDotNetCore/QueryStrings/Internal/PaginationQueryStringParameterReader.cs b/src/JsonApiDotNetCore/QueryStrings/Internal/PaginationQueryStringParameterReader.cs
index 416b48f4de..3e4293c5e0 100644
--- a/src/JsonApiDotNetCore/QueryStrings/Internal/PaginationQueryStringParameterReader.cs
+++ b/src/JsonApiDotNetCore/QueryStrings/Internal/PaginationQueryStringParameterReader.cs
@@ -53,7 +53,7 @@ public virtual void Read(string parameterName, StringValues parameterValue)
{
try
{
- PaginationQueryStringValueExpression constraint = GetPageConstraint(parameterValue);
+ PaginationQueryStringValueExpression constraint = GetPageConstraint(parameterValue.ToString());
if (constraint.Elements.Any(element => element.Scope == null))
{
diff --git a/src/JsonApiDotNetCore/QueryStrings/Internal/SortQueryStringParameterReader.cs b/src/JsonApiDotNetCore/QueryStrings/Internal/SortQueryStringParameterReader.cs
index 060d0c9986..5e5842c960 100644
--- a/src/JsonApiDotNetCore/QueryStrings/Internal/SortQueryStringParameterReader.cs
+++ b/src/JsonApiDotNetCore/QueryStrings/Internal/SortQueryStringParameterReader.cs
@@ -62,7 +62,7 @@ public virtual void Read(string parameterName, StringValues parameterValue)
try
{
ResourceFieldChainExpression? scope = GetScope(parameterName);
- SortExpression sort = GetSort(parameterValue, scope);
+ SortExpression sort = GetSort(parameterValue.ToString(), scope);
var expressionInScope = new ExpressionInScope(scope, sort);
_constraints.Add(expressionInScope);
diff --git a/src/JsonApiDotNetCore/QueryStrings/Internal/SparseFieldSetQueryStringParameterReader.cs b/src/JsonApiDotNetCore/QueryStrings/Internal/SparseFieldSetQueryStringParameterReader.cs
index fb4f665873..09c3c0ede8 100644
--- a/src/JsonApiDotNetCore/QueryStrings/Internal/SparseFieldSetQueryStringParameterReader.cs
+++ b/src/JsonApiDotNetCore/QueryStrings/Internal/SparseFieldSetQueryStringParameterReader.cs
@@ -69,7 +69,7 @@ public virtual void Read(string parameterName, StringValues parameterValue)
try
{
ResourceType targetResourceType = GetSparseFieldType(parameterName);
- SparseFieldSetExpression sparseFieldSet = GetSparseFieldSet(parameterValue, targetResourceType);
+ SparseFieldSetExpression sparseFieldSet = GetSparseFieldSet(parameterValue.ToString(), targetResourceType);
_sparseFieldTableBuilder[targetResourceType] = sparseFieldSet;
}
diff --git a/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs b/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs
index 653db6129a..7cdd114301 100644
--- a/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs
+++ b/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs
@@ -471,7 +471,7 @@ private IEnumerable GetRightValueToStoreForAddToToMany(TResource leftResource, H
if (rightResourceIdsStored.Any())
{
- rightResourceIdsStored.AddRange(rightResourceIdsToAdd);
+ rightResourceIdsStored.UnionWith(rightResourceIdsToAdd);
return rightResourceIdsStored;
}
diff --git a/src/JsonApiDotNetCore/Resources/OperationContainer.cs b/src/JsonApiDotNetCore/Resources/OperationContainer.cs
index a066943c82..88ea29ecdc 100644
--- a/src/JsonApiDotNetCore/Resources/OperationContainer.cs
+++ b/src/JsonApiDotNetCore/Resources/OperationContainer.cs
@@ -58,6 +58,6 @@ private void AddSecondaryResources(RelationshipAttribute relationship, HashSet rightResources = CollectionConverter.ExtractResources(rightValue);
- secondaryResources.AddRange(rightResources);
+ secondaryResources.UnionWith(rightResources);
}
}
diff --git a/src/JsonApiDotNetCore/Resources/TargetedFields.cs b/src/JsonApiDotNetCore/Resources/TargetedFields.cs
index fe4701c61e..4d40fc240d 100644
--- a/src/JsonApiDotNetCore/Resources/TargetedFields.cs
+++ b/src/JsonApiDotNetCore/Resources/TargetedFields.cs
@@ -18,8 +18,8 @@ public void CopyFrom(ITargetedFields other)
{
Clear();
- Attributes.AddRange(other.Attributes);
- Relationships.AddRange(other.Relationships);
+ Attributes.UnionWith(other.Attributes);
+ Relationships.UnionWith(other.Relationships);
}
public void Clear()
diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/RelationshipDataAdapter.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/RelationshipDataAdapter.cs
index ac1e25746b..0e90f7df07 100644
--- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/RelationshipDataAdapter.cs
+++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/RelationshipDataAdapter.cs
@@ -111,7 +111,7 @@ private IEnumerable ConvertToManyRelationshipData(SingleOrManyData(IdentifiableComparer.Instance);
- resourceSet.AddRange(rightResources);
+ resourceSet.UnionWith(rightResources);
return resourceSet;
}
}
diff --git a/src/JsonApiDotNetCore/Serialization/Response/LinkBuilder.cs b/src/JsonApiDotNetCore/Serialization/Response/LinkBuilder.cs
index ea0eb197df..fb86eb084c 100644
--- a/src/JsonApiDotNetCore/Serialization/Response/LinkBuilder.cs
+++ b/src/JsonApiDotNetCore/Serialization/Response/LinkBuilder.cs
@@ -140,13 +140,13 @@ private void SetPaginationInTopLevelLinks(ResourceType resourceType, TopLevelLin
private string? CalculatePageSizeValue(PageSize? topPageSize, ResourceType resourceType)
{
- string pageSizeParameterValue = HttpContext.Request.Query[PageSizeParameterName];
+ string? pageSizeParameterValue = HttpContext.Request.Query[PageSizeParameterName];
PageSize? newTopPageSize = Equals(topPageSize, _options.DefaultPageSize) ? null : topPageSize;
return ChangeTopPageSize(pageSizeParameterValue, newTopPageSize, resourceType);
}
- private string? ChangeTopPageSize(string pageSizeParameterValue, PageSize? topPageSize, ResourceType resourceType)
+ private string? ChangeTopPageSize(string? pageSizeParameterValue, PageSize? topPageSize, ResourceType resourceType)
{
IImmutableList elements = ParsePageSizeExpression(pageSizeParameterValue, resourceType);
int elementInTopScopeIndex = elements.FindIndex(expression => expression.Scope == null);
diff --git a/test/AnnotationTests/AnnotationTests.csproj b/test/AnnotationTests/AnnotationTests.csproj
index 51df20d735..7b221a9a42 100644
--- a/test/AnnotationTests/AnnotationTests.csproj
+++ b/test/AnnotationTests/AnnotationTests.csproj
@@ -4,12 +4,6 @@
latest
-
-
- PreserveNewest
-
-
-
diff --git a/test/DiscoveryTests/DiscoveryTests.csproj b/test/DiscoveryTests/DiscoveryTests.csproj
index 2f1048de3f..abbec3ed98 100644
--- a/test/DiscoveryTests/DiscoveryTests.csproj
+++ b/test/DiscoveryTests/DiscoveryTests.csproj
@@ -3,12 +3,6 @@
$(TargetFrameworkName)
-
-
- PreserveNewest
-
-
-
diff --git a/test/DiscoveryTests/xunit.runner.json b/test/DiscoveryTests/xunit.runner.json
deleted file mode 100644
index 9db029ba52..0000000000
--- a/test/DiscoveryTests/xunit.runner.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "parallelizeAssembly": false,
- "parallelizeTestCollections": false
-}
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/OperationsDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/OperationsDbContext.cs
index 26dd815521..6fd7817ba7 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/OperationsDbContext.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/OperationsDbContext.cs
@@ -31,5 +31,7 @@ protected override void OnModelCreating(ModelBuilder builder)
builder.Entity()
.HasMany(musicTrack => musicTrack.OccursIn)
.WithMany(playlist => playlist.Tracks);
+
+ base.OnModelCreating(builder);
}
}
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/QueryStrings/MusicTrackReleaseDefinition.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/QueryStrings/MusicTrackReleaseDefinition.cs
index 41aa048ecb..65ab4a4344 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/QueryStrings/MusicTrackReleaseDefinition.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/QueryStrings/MusicTrackReleaseDefinition.cs
@@ -32,7 +32,7 @@ private IQueryable FilterOnRecentlyReleased(IQueryable s
{
IQueryable tracks = source;
- if (bool.Parse(parameterValue))
+ if (bool.Parse(parameterValue.ToString()))
{
tracks = tracks.Where(musicTrack => musicTrack.ReleasedAt < _systemClock.UtcNow && musicTrack.ReleasedAt > _systemClock.UtcNow.AddMonths(-3));
}
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Transactions/AtomicTransactionConsistencyTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Transactions/AtomicTransactionConsistencyTests.cs
index 97f0e08ff5..46ef0c4784 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Transactions/AtomicTransactionConsistencyTests.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Transactions/AtomicTransactionConsistencyTests.cs
@@ -9,7 +9,8 @@
namespace JsonApiDotNetCoreTests.IntegrationTests.AtomicOperations.Transactions;
-public sealed class AtomicTransactionConsistencyTests : IClassFixture, OperationsDbContext>>
+public sealed class AtomicTransactionConsistencyTests
+ : IClassFixture, OperationsDbContext>>, IAsyncLifetime
{
private readonly IntegrationTestContext, OperationsDbContext> _testContext;
private readonly OperationsFakers _fakers = new();
@@ -27,7 +28,7 @@ public AtomicTransactionConsistencyTests(IntegrationTestContext();
string postgresPassword = Environment.GetEnvironmentVariable("PGPASSWORD") ?? "postgres";
- string dbConnectionString = $"Host=localhost;Port=5432;Database=JsonApiTest-{Guid.NewGuid():N};User ID=postgres;Password={postgresPassword}";
+ string dbConnectionString = $"Host=localhost;Port=5432;Database=JsonApiTest-Extra-{Guid.NewGuid():N};User ID=postgres;Password={postgresPassword}";
services.AddDbContext(options => options.UseNpgsql(dbConnectionString));
});
@@ -158,4 +159,22 @@ public async Task Cannot_use_distributed_transaction()
error.Source.ShouldNotBeNull();
error.Source.Pointer.Should().Be("/atomic:operations[0]");
}
+
+ public Task InitializeAsync()
+ {
+ return Task.CompletedTask;
+ }
+
+ Task IAsyncLifetime.DisposeAsync()
+ {
+ return DeleteExtraDatabaseAsync();
+ }
+
+ private async Task DeleteExtraDatabaseAsync()
+ {
+ await using AsyncServiceScope scope = _testContext.Factory.Services.CreateAsyncScope();
+ var dbContext = scope.ServiceProvider.GetRequiredService();
+
+ await dbContext.Database.EnsureDeletedAsync();
+ }
}
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CompositeDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CompositeDbContext.cs
index b745208cae..d4850ad428 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CompositeDbContext.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CompositeDbContext.cs
@@ -39,5 +39,7 @@ protected override void OnModelCreating(ModelBuilder builder)
builder.Entity()
.HasMany(car => car.PreviousDealerships)
.WithMany(dealership => dealership.SoldCars);
+
+ base.OnModelCreating(builder);
}
}
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/CustomRouteTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/CustomRouteTests.cs
index 572f2baeed..e89641470d 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/CustomRouteTests.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/CustomRouteTests.cs
@@ -67,12 +67,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext =>
public async Task Can_get_resources_at_custom_action_method()
{
// Arrange
- List town = _fakers.Town.Generate(7);
+ List towns = _fakers.Town.Generate(7);
await _testContext.RunOnDatabaseAsync(async dbContext =>
{
await dbContext.ClearTableAsync();
- dbContext.Towns.AddRange(town);
+ dbContext.Towns.AddRange(towns);
await dbContext.SaveChangesAsync();
});
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/EagerLoadingDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/EagerLoadingDbContext.cs
index 030a1a447b..a31deab9a8 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/EagerLoadingDbContext.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/EagerLoadingDbContext.cs
@@ -34,5 +34,7 @@ protected override void OnModelCreating(ModelBuilder builder)
.HasOne(building => building.SecondaryDoor)
.WithOne()
.HasForeignKey("SecondaryDoorId");
+
+ base.OnModelCreating(builder);
}
}
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/ModelState/ModelStateDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/ModelState/ModelStateDbContext.cs
index 73f3241f28..1bfdb1a28e 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/ModelState/ModelStateDbContext.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/ModelState/ModelStateDbContext.cs
@@ -37,5 +37,7 @@ protected override void OnModelCreating(ModelBuilder builder)
builder.Entity()
.HasOne(systemDirectory => systemDirectory.AlsoSelf)
.WithOne();
+
+ base.OnModelCreating(builder);
}
}
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/LinksDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/LinksDbContext.cs
index ffd2333fbe..149b29b785 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/LinksDbContext.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/LinksDbContext.cs
@@ -24,5 +24,7 @@ protected override void OnModelCreating(ModelBuilder builder)
.HasOne(photo => photo.Location)
.WithOne(location => location.Photo)
.HasForeignKey("LocationId");
+
+ base.OnModelCreating(builder);
}
}
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/MultiTenancy/MultiTenancyDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/MultiTenancy/MultiTenancyDbContext.cs
index 8e1fcd8350..69a6459303 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/MultiTenancy/MultiTenancyDbContext.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/MultiTenancy/MultiTenancyDbContext.cs
@@ -31,5 +31,7 @@ protected override void OnModelCreating(ModelBuilder builder)
builder.Entity()
.HasQueryFilter(webProduct => webProduct.Shop.TenantId == _tenantProvider.TenantId);
+
+ base.OnModelCreating(builder);
}
}
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterDbContext.cs
index 1b939ee9a1..35e7b4e51e 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterDbContext.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterDbContext.cs
@@ -21,5 +21,7 @@ protected override void OnModelCreating(ModelBuilder builder)
builder.Entity()
.Property(resource => resource.SomeDateTimeInLocalZone)
.HasColumnType("timestamp without time zone");
+
+ base.OnModelCreating(builder);
}
}
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterOperatorTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterOperatorTests.cs
index 0abad96024..6d000f6433 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterOperatorTests.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterOperatorTests.cs
@@ -466,6 +466,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext =>
}
[Theory]
+ [InlineData("yes", "no", "'yes'")]
[InlineData("two", "one two", "'one','two','three'")]
[InlineData("two", "nine", "'one','two','three','four','five'")]
public async Task Can_filter_in_set(string matchingText, string nonMatchingText, string filterText)
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/QueryStringDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/QueryStringDbContext.cs
index 131bfe19fe..473a7428ba 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/QueryStringDbContext.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/QueryStringDbContext.cs
@@ -37,5 +37,7 @@ protected override void OnModelCreating(ModelBuilder builder)
.HasOne(man => man.Wife)
.WithOne(woman => woman.Husband)
.HasForeignKey();
+
+ base.OnModelCreating(builder);
}
}
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/ReadWriteDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/ReadWriteDbContext.cs
index d25acf8a06..4f3d1080cf 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/ReadWriteDbContext.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/ReadWriteDbContext.cs
@@ -49,5 +49,7 @@ protected override void OnModelCreating(ModelBuilder builder)
left => left
.HasOne(joinEntity => joinEntity.ToItem)
.WithMany());
+
+ base.OnModelCreating(builder);
}
}
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/RemoveFromToManyRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/RemoveFromToManyRelationshipTests.cs
index eef972dd1f..ed9e4e7936 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/RemoveFromToManyRelationshipTests.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/RemoveFromToManyRelationshipTests.cs
@@ -1142,7 +1142,7 @@ private void RemoveFromSubscribers(WorkItem workItem, ISet rightR
{
if (!workItem.Subscribers.IsNullOrEmpty())
{
- PreloadedSubscribers.AddRange(workItem.Subscribers);
+ PreloadedSubscribers.UnionWith(workItem.Subscribers);
}
foreach (long subscriberId in ExtraSubscribersIdsToRemove)
@@ -1158,7 +1158,7 @@ private void RemoveFromTags(WorkItem workItem, ISet rightResource
{
if (!workItem.Tags.IsNullOrEmpty())
{
- PreloadedTags.AddRange(workItem.Tags);
+ PreloadedTags.UnionWith(workItem.Tags);
}
foreach (int tagId in ExtraTagIdsToRemove)
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/UpdateToOneRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/UpdateToOneRelationshipTests.cs
index a492cc4826..b96fcd6fff 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/UpdateToOneRelationshipTests.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/UpdateToOneRelationshipTests.cs
@@ -66,7 +66,7 @@ public async Task Can_clear_OneToOne_relationship()
await _testContext.RunOnDatabaseAsync(async dbContext =>
{
- dbContext.Groups.AddRange(existingGroup);
+ dbContext.Groups.Add(existingGroup);
await dbContext.SaveChangesAsync();
});
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateToOneRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateToOneRelationshipTests.cs
index 81faaa8297..f96f4a9efa 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateToOneRelationshipTests.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateToOneRelationshipTests.cs
@@ -209,7 +209,7 @@ public async Task Can_clear_OneToOne_relationship()
await _testContext.RunOnDatabaseAsync(async dbContext =>
{
- dbContext.RgbColors.AddRange(existingColor);
+ dbContext.RgbColors.Add(existingColor);
await dbContext.SaveChangesAsync();
});
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/RequiredRelationships/DefaultBehaviorDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/RequiredRelationships/DefaultBehaviorDbContext.cs
index 6ed4deaeff..5b0b839c63 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/RequiredRelationships/DefaultBehaviorDbContext.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/RequiredRelationships/DefaultBehaviorDbContext.cs
@@ -33,5 +33,7 @@ protected override void OnModelCreating(ModelBuilder builder)
.HasOne(order => order.Shipment)
.WithOne(shipment => shipment.Order)
.HasForeignKey("OrderId");
+
+ base.OnModelCreating(builder);
}
}
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/MoonDefinition.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/MoonDefinition.cs
index bdd75a9aff..2b904434ad 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/MoonDefinition.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/MoonDefinition.cs
@@ -51,7 +51,7 @@ public override QueryStringParameterHandlers OnRegisterQueryableHandlersFo
private static IQueryable FilterByRadius(IQueryable source, StringValues parameterValue)
{
- bool isFilterOnLargerThan = bool.Parse(parameterValue);
+ bool isFilterOnLargerThan = bool.Parse(parameterValue.ToString());
return isFilterOnLargerThan ? source.Where(moon => moon.SolarRadius > 1m) : source.Where(moon => moon.SolarRadius <= 1m);
}
}
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Serialization/SerializationDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Serialization/SerializationDbContext.cs
index 7f62a63b73..4bfb7aa709 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Serialization/SerializationDbContext.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Serialization/SerializationDbContext.cs
@@ -22,5 +22,7 @@ protected override void OnModelCreating(ModelBuilder builder)
builder.Entity()
.HasMany(scholarship => scholarship.Participants)
.WithOne(student => student.Scholarship!);
+
+ base.OnModelCreating(builder);
}
}
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceReadTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceReadTests.cs
index 3a7b60e93d..ebca28dac9 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceReadTests.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceReadTests.cs
@@ -2429,7 +2429,7 @@ public async Task Can_sort_on_derived_attribute_from_resource_definition_using_e
await _testContext.RunOnDatabaseAsync(async dbContext =>
{
- await dbContext.ClearTableAsync();
+ await dbContext.ClearTableAsync();
dbContext.Wheels.AddRange(chromeWheel1, chromeWheel2, chromeWheel3, carbonWheel1, carbonWheel2);
await dbContext.SaveChangesAsync();
});
@@ -2487,7 +2487,7 @@ public async Task Can_sort_on_derived_attribute_from_resource_definition_using_l
await _testContext.RunOnDatabaseAsync(async dbContext =>
{
- await dbContext.ClearTableAsync();
+ await dbContext.ClearTableAsync();
dbContext.Wheels.AddRange(chromeWheel1, chromeWheel2, chromeWheel3, carbonWheel1, carbonWheel2);
await dbContext.SaveChangesAsync();
});
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerType/TablePerTypeDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerType/TablePerTypeDbContext.cs
index a1549e6332..7c50ee5573 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerType/TablePerTypeDbContext.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerType/TablePerTypeDbContext.cs
@@ -32,5 +32,7 @@ protected override void OnModelCreating(ModelBuilder builder)
builder.Entity().ToTable("GenericProperties");
builder.Entity().ToTable("StringProperties");
builder.Entity().ToTable("NumberProperties");
+
+ base.OnModelCreating(builder);
}
}
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/SoftDeletion/SoftDeletionDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/SoftDeletion/SoftDeletionDbContext.cs
index 2a19ba74b4..3e98950be0 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/SoftDeletion/SoftDeletionDbContext.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/SoftDeletion/SoftDeletionDbContext.cs
@@ -24,5 +24,7 @@ protected override void OnModelCreating(ModelBuilder builder)
builder.Entity()
.HasQueryFilter(department => department.SoftDeletedAt == null);
+
+ base.OnModelCreating(builder);
}
}
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/ZeroKeyDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/ZeroKeyDbContext.cs
index 301a7b6d7b..3e93768683 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/ZeroKeyDbContext.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/ZeroKeyDbContext.cs
@@ -27,5 +27,7 @@ protected override void OnModelCreating(ModelBuilder builder)
builder.Entity()
.HasOne(player => player.ActiveGame)
.WithMany(game => game.ActivePlayers);
+
+ base.OnModelCreating(builder);
}
}
diff --git a/test/JsonApiDotNetCoreTests/JsonApiDotNetCoreTests.csproj b/test/JsonApiDotNetCoreTests/JsonApiDotNetCoreTests.csproj
index ddb7550e5e..22d50630ca 100644
--- a/test/JsonApiDotNetCoreTests/JsonApiDotNetCoreTests.csproj
+++ b/test/JsonApiDotNetCoreTests/JsonApiDotNetCoreTests.csproj
@@ -3,12 +3,6 @@
$(TargetFrameworkName)
-
-
- PreserveNewest
-
-
-
{
webBuilder.ConfigureServices(services =>
- services.AddDbContext(options => options.UseInMemoryDatabase("db")));
+ services.AddDbContext(options => options.UseInMemoryDatabase(Guid.NewGuid().ToString())));
webBuilder.UseStartup>();
diff --git a/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/FilterParseTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/FilterParseTests.cs
index e471218ff6..562270a358 100644
--- a/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/FilterParseTests.cs
+++ b/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/FilterParseTests.cs
@@ -86,7 +86,7 @@ public void Reader_Is_Enabled(JsonApiQueryStringParameters parametersDisabled, b
[InlineData("filter", "any(null,'a','b')", "Attribute 'null' does not exist on resource type 'blogs'.")]
[InlineData("filter", "any('a','b','c')", "Field name expected.")]
[InlineData("filter", "any(title,'b','c',)", "Value between quotes expected.")]
- [InlineData("filter", "any(title,'b')", ", expected.")]
+ [InlineData("filter", "any(title)", ", expected.")]
[InlineData("filter[posts]", "any(author,'a','b')", "Attribute 'author' does not exist on resource type 'blogPosts'.")]
[InlineData("filter", "and(", "Filter function expected.")]
[InlineData("filter", "or(equals(title,'some'),equals(title,'other')", ") expected.")]
@@ -146,6 +146,7 @@ public void Reader_Read_Fails(string parameterName, string parameterValue, strin
[InlineData("filter", "contains(title,'this')", null, "contains(title,'this')")]
[InlineData("filter", "startsWith(title,'this')", null, "startsWith(title,'this')")]
[InlineData("filter", "endsWith(title,'this')", null, "endsWith(title,'this')")]
+ [InlineData("filter", "any(title,'this')", null, "any(title,'this')")]
[InlineData("filter", "any(title,'this','that','there')", null, "any(title,'that','there','this')")]
[InlineData("filter", "and(contains(title,'sales'),contains(title,'marketing'),contains(title,'advertising'))", null,
"and(contains(title,'sales'),contains(title,'marketing'),contains(title,'advertising'))")]
diff --git a/test/JsonApiDotNetCoreTests/UnitTests/Serialization/Response/ResponseModelAdapterTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/Serialization/Response/ResponseModelAdapterTests.cs
index d9459f7ec1..39279181dd 100644
--- a/test/JsonApiDotNetCoreTests/UnitTests/Serialization/Response/ResponseModelAdapterTests.cs
+++ b/test/JsonApiDotNetCoreTests/UnitTests/Serialization/Response/ResponseModelAdapterTests.cs
@@ -40,6 +40,7 @@ public void Resources_in_deeply_nested_circular_chain_are_written_in_relationshi
// Assert
string text = JsonSerializer.Serialize(document, new JsonSerializerOptions(options.SerializerWriteOptions));
+ // ReSharper disable StringLiteralTypo
text.Should().BeJson(@"{
""data"": {
""type"": ""articles"",
@@ -145,6 +146,7 @@ public void Resources_in_deeply_nested_circular_chain_are_written_in_relationshi
}
]
}");
+ // ReSharper restore StringLiteralTypo
}
[Fact]
@@ -177,6 +179,7 @@ public void Resources_in_deeply_nested_circular_chains_are_written_in_relationsh
// Assert
string text = JsonSerializer.Serialize(document, new JsonSerializerOptions(options.SerializerWriteOptions));
+ // ReSharper disable StringLiteralTypo
text.Should().BeJson(@"{
""data"": [
{
@@ -299,6 +302,7 @@ public void Resources_in_deeply_nested_circular_chains_are_written_in_relationsh
}
]
}");
+ // ReSharper restore StringLiteralTypo
}
[Fact]
@@ -335,6 +339,7 @@ public void Resources_in_overlapping_deeply_nested_circular_chains_are_written_i
// Assert
string text = JsonSerializer.Serialize(document, new JsonSerializerOptions(options.SerializerWriteOptions));
+ // ReSharper disable StringLiteralTypo
text.Should().BeJson(@"{
""data"": {
""type"": ""articles"",
@@ -514,6 +519,7 @@ public void Resources_in_overlapping_deeply_nested_circular_chains_are_written_i
}
]
}");
+ // ReSharper restore StringLiteralTypo
}
[Fact]
diff --git a/test/JsonApiDotNetCoreTests/xunit.runner.json b/test/JsonApiDotNetCoreTests/xunit.runner.json
deleted file mode 100644
index 8f5f10571b..0000000000
--- a/test/JsonApiDotNetCoreTests/xunit.runner.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "parallelizeAssembly": false,
- "parallelizeTestCollections": false,
- "maxParallelThreads": 1
-}
diff --git a/test/MultiDbContextTests/MultiDbContextTests.csproj b/test/MultiDbContextTests/MultiDbContextTests.csproj
index a5d0715a2a..b08c25805f 100644
--- a/test/MultiDbContextTests/MultiDbContextTests.csproj
+++ b/test/MultiDbContextTests/MultiDbContextTests.csproj
@@ -3,12 +3,6 @@
$(TargetFrameworkName)
-
-
- PreserveNewest
-
-
-
diff --git a/test/MultiDbContextTests/xunit.runner.json b/test/MultiDbContextTests/xunit.runner.json
deleted file mode 100644
index 8f5f10571b..0000000000
--- a/test/MultiDbContextTests/xunit.runner.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "parallelizeAssembly": false,
- "parallelizeTestCollections": false,
- "maxParallelThreads": 1
-}
diff --git a/test/TestBuildingBlocks/DbContextExtensions.cs b/test/TestBuildingBlocks/DbContextExtensions.cs
index b570cbf655..5bb3f81a14 100644
--- a/test/TestBuildingBlocks/DbContextExtensions.cs
+++ b/test/TestBuildingBlocks/DbContextExtensions.cs
@@ -1,6 +1,5 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
-using Npgsql;
namespace TestBuildingBlocks;
@@ -36,17 +35,7 @@ private static async Task ClearTablesAsync(this DbContext dbContext, params Type
}
string tableName = entityType.GetTableName()!;
-
- // PERF: We first try to clear the table, which is fast and usually succeeds, unless foreign key constraints are violated.
- // In that case, we recursively delete all related data, which is slow.
- try
- {
- await dbContext.Database.ExecuteSqlRawAsync($"delete from \"{tableName}\"");
- }
- catch (PostgresException)
- {
- await dbContext.Database.ExecuteSqlRawAsync($"truncate table \"{tableName}\" cascade");
- }
+ await dbContext.Database.ExecuteSqlRawAsync($"delete from \"{tableName}\"");
}
}
}
diff --git a/test/TestBuildingBlocks/IntegrationTest.cs b/test/TestBuildingBlocks/IntegrationTest.cs
index 4fb2e5cd26..92f49879fc 100644
--- a/test/TestBuildingBlocks/IntegrationTest.cs
+++ b/test/TestBuildingBlocks/IntegrationTest.cs
@@ -2,14 +2,18 @@
using System.Text;
using System.Text.Json;
using JsonApiDotNetCore.Middleware;
+using Xunit;
namespace TestBuildingBlocks;
///
-/// A base class for tests that conveniently enables to execute HTTP requests against JSON:API endpoints.
+/// A base class for tests that conveniently enables to execute HTTP requests against JSON:API endpoints. It throttles tests that are running in parallel
+/// to avoid exceeding the maximum active database connections.
///
-public abstract class IntegrationTest
+public abstract class IntegrationTest : IAsyncLifetime
{
+ private static readonly SemaphoreSlim ThrottleSemaphore = new(64);
+
protected abstract JsonSerializerOptions SerializerOptions { get; }
public async Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecuteHeadAsync(string requestUrl,
@@ -105,4 +109,15 @@ public abstract class IntegrationTest
throw new FormatException($"Failed to deserialize response body to JSON:\n{responseText}", exception);
}
}
+
+ public async Task InitializeAsync()
+ {
+ await ThrottleSemaphore.WaitAsync();
+ }
+
+ public virtual Task DisposeAsync()
+ {
+ _ = ThrottleSemaphore.Release();
+ return Task.CompletedTask;
+ }
}
diff --git a/test/TestBuildingBlocks/IntegrationTestContext.cs b/test/TestBuildingBlocks/IntegrationTestContext.cs
index bccf7d8bf3..7856ba67f9 100644
--- a/test/TestBuildingBlocks/IntegrationTestContext.cs
+++ b/test/TestBuildingBlocks/IntegrationTestContext.cs
@@ -24,7 +24,7 @@ namespace TestBuildingBlocks;
/// The Entity Framework Core database context, which can be defined in the test project or API project.
///
[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)]
-public class IntegrationTestContext : IntegrationTest, IDisposable
+public class IntegrationTestContext : IntegrationTest
where TStartup : class
where TDbContext : TestableDbContext
{
@@ -103,16 +103,6 @@ private WebApplicationFactory CreateFactory()
return factoryWithConfiguredContentRoot;
}
- public void Dispose()
- {
- if (_lazyFactory.IsValueCreated)
- {
- RunOnDatabaseAsync(async dbContext => await dbContext.Database.EnsureDeletedAsync()).Wait();
-
- _lazyFactory.Value.Dispose();
- }
- }
-
public void ConfigureLogging(Action loggingConfiguration)
{
_loggingConfiguration = loggingConfiguration;
@@ -136,6 +126,22 @@ public async Task RunOnDatabaseAsync(Func asyncAction)
await asyncAction(dbContext);
}
+ public override async Task DisposeAsync()
+ {
+ try
+ {
+ if (_lazyFactory.IsValueCreated)
+ {
+ await RunOnDatabaseAsync(async dbContext => await dbContext.Database.EnsureDeletedAsync());
+ await _lazyFactory.Value.DisposeAsync();
+ }
+ }
+ finally
+ {
+ await base.DisposeAsync();
+ }
+ }
+
private sealed class IntegrationTestWebApplicationFactory : WebApplicationFactory
{
private Action? _loggingConfiguration;
diff --git a/test/TestBuildingBlocks/TestBuildingBlocks.csproj b/test/TestBuildingBlocks/TestBuildingBlocks.csproj
index 5600104fda..ce8c54ef3b 100644
--- a/test/TestBuildingBlocks/TestBuildingBlocks.csproj
+++ b/test/TestBuildingBlocks/TestBuildingBlocks.csproj
@@ -10,7 +10,7 @@
-
+
diff --git a/test/TestBuildingBlocks/TestableDbContext.cs b/test/TestBuildingBlocks/TestableDbContext.cs
index d40db11c03..18ef090baa 100644
--- a/test/TestBuildingBlocks/TestableDbContext.cs
+++ b/test/TestBuildingBlocks/TestableDbContext.cs
@@ -1,6 +1,7 @@
using System.Diagnostics;
using JsonApiDotNetCore;
using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.Extensions.Logging;
namespace TestBuildingBlocks;
@@ -17,4 +18,15 @@ protected override void OnConfiguring(DbContextOptionsBuilder builder)
// Writes SQL statements to the Output Window when debugging.
builder.LogTo(message => Debug.WriteLine(message), DbLoggerCategory.Database.Name.AsArray(), LogLevel.Information);
}
+
+ protected override void OnModelCreating(ModelBuilder builder)
+ {
+ foreach (IMutableForeignKey foreignKey in builder.Model.GetEntityTypes().SelectMany(entityType => entityType.GetForeignKeys()))
+ {
+ if (foreignKey.DeleteBehavior == DeleteBehavior.ClientSetNull)
+ {
+ foreignKey.DeleteBehavior = DeleteBehavior.SetNull;
+ }
+ }
+ }
}
diff --git a/test/UnitTests/Extensions/ServiceCollectionExtensionsTests.cs b/test/UnitTests/Extensions/ServiceCollectionExtensionsTests.cs
index a90c3851ee..0cb24d8025 100644
--- a/test/UnitTests/Extensions/ServiceCollectionExtensionsTests.cs
+++ b/test/UnitTests/Extensions/ServiceCollectionExtensionsTests.cs
@@ -25,7 +25,7 @@ public void RegisterResource_DeviatingDbContextPropertyName_RegistersCorrectly()
// Arrange
var services = new ServiceCollection();
services.AddLogging();
- services.AddDbContext(options => options.UseInMemoryDatabase("UnitTestDb"));
+ services.AddDbContext(options => options.UseInMemoryDatabase(Guid.NewGuid().ToString()));
// Act
services.AddJsonApi();
diff --git a/test/UnitTests/UnitTests.csproj b/test/UnitTests/UnitTests.csproj
index eb3383fbdf..3166fe27e1 100644
--- a/test/UnitTests/UnitTests.csproj
+++ b/test/UnitTests/UnitTests.csproj
@@ -3,12 +3,6 @@
$(TargetFrameworkName)
-
-
- PreserveNewest
-
-
-
diff --git a/test/UnitTests/xunit.runner.json b/test/UnitTests/xunit.runner.json
deleted file mode 100644
index 9db029ba52..0000000000
--- a/test/UnitTests/xunit.runner.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "parallelizeAssembly": false,
- "parallelizeTestCollections": false
-}