Skip to content

Commit

Permalink
Replace FluentAssertions with Shouldly
Browse files Browse the repository at this point in the history
  • Loading branch information
damianh committed Feb 5, 2025
1 parent 69d4a0e commit cb3d63b
Show file tree
Hide file tree
Showing 175 changed files with 4,582 additions and 4,508 deletions.
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# MacOs
.DS_Store

# Rider
.idea

Expand Down Expand Up @@ -214,4 +217,7 @@ src/IdentityServer4/host/identityserver.db
tempkey.jwk
keys
*.key
test/Configuration.IntegrationTests/CoverageReports
test/Configuration.IntegrationTests/CoverageReports
Duende.BFF.db
*.db-shm
*.db-wal
15 changes: 15 additions & 0 deletions identity-server/Duende.IdentityServer.sln
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duende.IdentityServer.Confi
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Configuration.IntegrationTests", "test\Configuration.IntegrationTests\Configuration.IntegrationTests.csproj", "{5882A7DB-BD70-481C-A249-3A422652AFD6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShouldlyExtensions", "..\shared\ShouldlyExtensions\ShouldlyExtensions.csproj", "{5C742DF6-1262-41BA-AA49-65C7E54435B4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -287,6 +289,18 @@ Global
{5882A7DB-BD70-481C-A249-3A422652AFD6}.Release|x64.Build.0 = Release|Any CPU
{5882A7DB-BD70-481C-A249-3A422652AFD6}.Release|x86.ActiveCfg = Release|Any CPU
{5882A7DB-BD70-481C-A249-3A422652AFD6}.Release|x86.Build.0 = Release|Any CPU
{5C742DF6-1262-41BA-AA49-65C7E54435B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5C742DF6-1262-41BA-AA49-65C7E54435B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5C742DF6-1262-41BA-AA49-65C7E54435B4}.Debug|x64.ActiveCfg = Debug|Any CPU
{5C742DF6-1262-41BA-AA49-65C7E54435B4}.Debug|x64.Build.0 = Debug|Any CPU
{5C742DF6-1262-41BA-AA49-65C7E54435B4}.Debug|x86.ActiveCfg = Debug|Any CPU
{5C742DF6-1262-41BA-AA49-65C7E54435B4}.Debug|x86.Build.0 = Debug|Any CPU
{5C742DF6-1262-41BA-AA49-65C7E54435B4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5C742DF6-1262-41BA-AA49-65C7E54435B4}.Release|Any CPU.Build.0 = Release|Any CPU
{5C742DF6-1262-41BA-AA49-65C7E54435B4}.Release|x64.ActiveCfg = Release|Any CPU
{5C742DF6-1262-41BA-AA49-65C7E54435B4}.Release|x64.Build.0 = Release|Any CPU
{5C742DF6-1262-41BA-AA49-65C7E54435B4}.Release|x86.ActiveCfg = Release|Any CPU
{5C742DF6-1262-41BA-AA49-65C7E54435B4}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -311,6 +325,7 @@ Global
{C0AE6878-A605-4EA9-8439-2EBB1EF09AAA} = {D5E9E8E5-4050-4B9A-9F1F-15FA3BDB0684}
{754825F1-5386-4343-A3AA-41D31B66179C} = {D5E9E8E5-4050-4B9A-9F1F-15FA3BDB0684}
{5882A7DB-BD70-481C-A249-3A422652AFD6} = {DF26567D-46BB-4720-8610-EC3D6AB9793C}
{5C742DF6-1262-41BA-AA49-65C7E54435B4} = {DF26567D-46BB-4720-8610-EC3D6AB9793C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FDB095BE-A04A-4440-ACA0-EDD7CF9CFD64}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" />
<PackageReference Include="FluentAssertions" />

<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// See LICENSE in the project root for license information.


using FluentAssertions;
using Shouldly;
using IntegrationTests.TestHosts;
using Xunit;
using Duende.IdentityServer.Configuration.Models.DynamicClientRegistration;
Expand Down Expand Up @@ -30,15 +30,15 @@ public async Task valid_request_creates_new_client()
var httpResponse = await ConfigurationHost.HttpClient!.PostAsJsonAsync("/connect/dcr", request);

var response = await httpResponse.Content.ReadFromJsonAsync<DynamicClientRegistrationResponse>();
response.Should().NotBeNull();
response.ShouldNotBeNull();
var newClient = await IdentityServerHost.GetClientAsync(response!.ClientId); // Not null already asserted
newClient.Should().NotBeNull();
newClient.ClientId.Should().Be(response.ClientId);
newClient.AllowedGrantTypes.Should().BeEquivalentTo(request.GrantTypes);
newClient.ClientName.Should().Be(request.ClientName);
newClient.ClientUri.Should().Be(request.ClientUri.ToString());
newClient.UserSsoLifetime.Should().Be(request.DefaultMaxAge);
newClient.ClientSecrets.Count.Should().Be(1);
newClient.ClientSecrets.Single().Value.Should().Be(response.ClientSecret.Sha256());
newClient.ShouldNotBeNull();
newClient.ClientId.ShouldBe(response.ClientId);
newClient.AllowedGrantTypes.ShouldBeEquivalentTo(request.GrantTypes);

Check failure on line 37 in identity-server/test/Configuration.IntegrationTests/DynamicClientRegistrationTests.cs

View workflow job for this annotation

GitHub Actions / Test Report - Configuration.IntegrationTests

IntegrationTests.DynamicClientRegistrationTests ► valid_request_creates_new_client

Failed test found in: identity-server/test/Configuration.IntegrationTests/TestResults/Tests.trx Error: Shouldly.ShouldAssertException : Comparing object equivalence, at path: newClient.AllowedGrantTypes Expected value to be System.String[] but was Duende.IdentityServer.Models.Client+GrantTypeValidatingHashSet
Raw output
Shouldly.ShouldAssertException : Comparing object equivalence, at path:
newClient.AllowedGrantTypes

    Expected value to be
System.String[]
    but was
Duende.IdentityServer.Models.Client+GrantTypeValidatingHashSet
   at IntegrationTests.DynamicClientRegistrationTests.valid_request_creates_new_client() in /home/runner/work/products/products/identity-server/test/Configuration.IntegrationTests/DynamicClientRegistrationTests.cs:line 37
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task, ConfigureAwaitOptions options)
--- End of stack trace from previous location ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task, ConfigureAwaitOptions options)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task, ConfigureAwaitOptions options)
newClient.ClientName.ShouldBe(request.ClientName);
newClient.ClientUri.ShouldBe(request.ClientUri.ToString());
newClient.UserSsoLifetime.ShouldBe(request.DefaultMaxAge);
newClient.ClientSecrets.Count.ShouldBe(1);
newClient.ClientSecrets.Single().Value.ShouldBe(response.ClientSecret.Sha256());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@


using System.Net;
using FluentAssertions;
using Shouldly;
using IntegrationTests.TestHosts;
using Xunit;
using Duende.IdentityServer.Configuration.Models.DynamicClientRegistration;
Expand All @@ -18,7 +18,7 @@ public class DynamicClientRegistrationValidationTests : ConfigurationIntegration
public async Task http_get_method_should_fail()
{
var response = await ConfigurationHost.HttpClient!.GetAsync("/connect/dcr");
response.StatusCode.Should().Be(HttpStatusCode.MethodNotAllowed);
response.StatusCode.ShouldBe(HttpStatusCode.MethodNotAllowed);
}

[Fact]
Expand All @@ -29,7 +29,7 @@ public async Task incorrect_content_type_should_fail()
{ "grant_types", "authorization_code" }
});
var response = await ConfigurationHost.HttpClient!.PostAsync("/connect/dcr", content);
response.StatusCode.Should().Be(HttpStatusCode.UnsupportedMediaType);
response.StatusCode.ShouldBe(HttpStatusCode.UnsupportedMediaType);
}

[Fact]
Expand All @@ -39,10 +39,10 @@ public async Task missing_grant_type_should_fail()
{
redirect_uris = new[] { "https://example.com/callback" }
});
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
response.StatusCode.ShouldBe(HttpStatusCode.BadRequest);

var error = await response.Content.ReadFromJsonAsync<DynamicClientRegistrationError>();
error?.Error.Should().Be("invalid_client_metadata");
error?.Error.ShouldBe("invalid_client_metadata");
}

[Fact]
Expand All @@ -53,10 +53,10 @@ public async Task unsupported_grant_type_should_fail()
redirect_uris = new[] { "https://example.com/callback" },
grant_types = new[] { "password" }
});
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
response.StatusCode.ShouldBe(HttpStatusCode.BadRequest);

var error = await response.Content.ReadFromJsonAsync<DynamicClientRegistrationError>();
error?.Error.Should().Be("invalid_client_metadata");
error?.Error.ShouldBe("invalid_client_metadata");
}

[Fact]
Expand All @@ -67,10 +67,10 @@ public async Task client_credentials_with_redirect_uri_should_fail()
redirect_uris = new[] { "https://example.com/callback" },
grant_types = new[] { "client_credentials" }
});
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
response.StatusCode.ShouldBe(HttpStatusCode.BadRequest);

var error = await response.Content.ReadFromJsonAsync<DynamicClientRegistrationError>();
error?.Error.Should().Be("invalid_redirect_uri");
error?.Error.ShouldBe("invalid_redirect_uri");
}

[Fact]
Expand All @@ -80,10 +80,10 @@ public async Task auth_code_without_redirect_uri_should_fail()
{
grant_types = new[] { "authorization_code", "client_credentials" }
});
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
response.StatusCode.ShouldBe(HttpStatusCode.BadRequest);

var error = await response.Content.ReadFromJsonAsync<DynamicClientRegistrationError>();
error?.Error.Should().Be("invalid_redirect_uri");
error?.Error.ShouldBe("invalid_redirect_uri");
}

[Fact]
Expand All @@ -93,10 +93,10 @@ public async Task client_credentials_and_refresh_token_should_fail()
{
grant_types = new[] { "client_credentials", "refresh_token" }
});
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
response.StatusCode.ShouldBe(HttpStatusCode.BadRequest);

var error = await response.Content.ReadFromJsonAsync<DynamicClientRegistrationError>();
error?.Error.Should().Be("invalid_client_metadata");
error?.Error.ShouldBe("invalid_client_metadata");
}

[Fact]
Expand All @@ -110,9 +110,9 @@ public async Task jwks_and_jwks_uri_used_together_should_fail()
JwksUri = new Uri("https://example.com")
}
);
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
response.StatusCode.ShouldBe(HttpStatusCode.BadRequest);

var error = await response.Content.ReadFromJsonAsync<DynamicClientRegistrationError>();
error?.Error.Should().Be("invalid_client_metadata");
error?.Error.ShouldBe("invalid_client_metadata");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="FluentAssertions" />

<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="FluentAssertions" />

<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" />
Expand All @@ -28,6 +28,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\shared\ShouldlyExtensions\ShouldlyExtensions.csproj" />
<ProjectReference Include="..\..\src\EntityFramework.Storage\Duende.IdentityServer.EntityFramework.Storage.csproj" />
<ProjectReference Include="..\..\src\IdentityServer\Duende.IdentityServer.csproj" />
<ProjectReference Include="..\..\src\Storage\Duende.IdentityServer.Storage.csproj" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
using Duende.IdentityServer.EntityFramework.Stores;
using Duende.IdentityServer.Models;
using Duende.IdentityServer.Services;
using FluentAssertions;
using Shouldly;
using Microsoft.EntityFrameworkCore;
using Xunit;
using Xunit.Sdk;
Expand Down Expand Up @@ -60,7 +60,7 @@ public async Task FindClientByIdAsync_WhenClientExists_ExpectClientReturned(DbCo
client = await store.FindClientByIdAsync(testClient.ClientId);
}

client.Should().NotBeNull();
client.ShouldNotBeNull();
}

[Theory, MemberData(nameof(TestDatabaseProviders))]
Expand Down Expand Up @@ -94,7 +94,7 @@ public async Task FindClientByIdAsync_WhenClientExistsWithCollections_ExpectClie
client = await store.FindClientByIdAsync(testClient.ClientId);
}

client.Should().BeEquivalentTo(testClient);
client.ShouldBeEquivalentTo(testClient);
}

[Theory, MemberData(nameof(TestDatabaseProviders))]
Expand Down Expand Up @@ -148,7 +148,7 @@ public async Task FindClientByIdAsync_WhenClientsExistWithManyCollections_Expect
#pragma warning disable xUnit1031 // Do not use blocking task operations in test method, suppressed because the task must have completed to enter this block
var client = task.Result;
#pragma warning restore xUnit1031 // Do not use blocking task operations in test method
client.Should().BeEquivalentTo(testClient);
client.ShouldBeEquivalentTo(testClient);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
using Duende.IdentityServer.EntityFramework.Stores;
using Duende.IdentityServer.Models;
using Duende.IdentityServer.Stores.Serialization;
using FluentAssertions;
using Shouldly;
using Duende.IdentityModel;
using Microsoft.EntityFrameworkCore.InMemory.Infrastructure.Internal;
using Xunit;
Expand Down Expand Up @@ -57,9 +57,9 @@ public async Task StoreDeviceAuthorizationAsync_WhenSuccessful_ExpectDeviceCodeA
{
var foundDeviceFlowCodes = context.DeviceFlowCodes.FirstOrDefault(x => x.DeviceCode == deviceCode);

foundDeviceFlowCodes.Should().NotBeNull();
foundDeviceFlowCodes?.DeviceCode.Should().Be(deviceCode);
foundDeviceFlowCodes?.UserCode.Should().Be(userCode);
foundDeviceFlowCodes.ShouldNotBeNull();
foundDeviceFlowCodes?.DeviceCode.ShouldBe(deviceCode);
foundDeviceFlowCodes?.UserCode.ShouldBe(userCode);
}
}

Expand All @@ -85,12 +85,12 @@ public async Task StoreDeviceAuthorizationAsync_WhenSuccessful_ExpectDataStored(
{
var foundDeviceFlowCodes = context.DeviceFlowCodes.FirstOrDefault(x => x.DeviceCode == deviceCode);

foundDeviceFlowCodes.Should().NotBeNull();
foundDeviceFlowCodes.ShouldNotBeNull();
var deserializedData = new PersistentGrantSerializer().Deserialize<DeviceCode>(foundDeviceFlowCodes?.Data);

deserializedData.CreationTime.Should().BeCloseTo(data.CreationTime, TimeSpan.FromMicroseconds(1));
deserializedData.ClientId.Should().Be(data.ClientId);
deserializedData.Lifetime.Should().Be(data.Lifetime);
deserializedData.CreationTime.ShouldBeCloseTo(data.CreationTime, TimeSpan.FromMicroseconds(1));
deserializedData.ClientId.ShouldBe(data.ClientId);
deserializedData.Lifetime.ShouldBe(data.Lifetime);
}
}

Expand Down Expand Up @@ -222,11 +222,11 @@ public async Task FindByUserCodeAsync_WhenUserCodeExists_ExpectDataRetrievedCorr
var store = new DeviceFlowStore(context, new PersistentGrantSerializer(), FakeLogger<DeviceFlowStore>.Create(), new NoneCancellationTokenProvider());
code = await store.FindByUserCodeAsync(testUserCode);
}

code.Should().BeEquivalentTo(expectedDeviceCodeData,
assertionOptions => assertionOptions.Excluding(x=> x.Subject));

code.Subject.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject && x.Value == expectedSubject).Should().NotBeNull();
code.ShouldBe(expectedDeviceCodeData);
//assertionOptions => assertionOptions.Excluding(x=> x.Subject));

code.Subject.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject && x.Value == expectedSubject).ShouldNotBeNull();
}

[Theory, MemberData(nameof(TestDatabaseProviders))]
Expand All @@ -236,7 +236,7 @@ public async Task FindByUserCodeAsync_WhenUserCodeDoesNotExist_ExpectNull(DbCont
{
var store = new DeviceFlowStore(context, new PersistentGrantSerializer(), FakeLogger<DeviceFlowStore>.Create(), new NoneCancellationTokenProvider());
var code = await store.FindByUserCodeAsync($"user_{Guid.NewGuid().ToString()}");
code.Should().BeNull();
code.ShouldBeNull();
}
}

Expand Down Expand Up @@ -279,10 +279,10 @@ public async Task FindByDeviceCodeAsync_WhenDeviceCodeExists_ExpectDataRetrieved
code = await store.FindByDeviceCodeAsync(testDeviceCode);
}

code.Should().BeEquivalentTo(expectedDeviceCodeData,
assertionOptions => assertionOptions.Excluding(x => x.Subject));
code.ShouldBe(expectedDeviceCodeData);
//assertionOptions => assertionOptions.Excluding(x => x.Subject));

code.Subject.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject && x.Value == expectedSubject).Should().NotBeNull();
code.Subject.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject && x.Value == expectedSubject).ShouldNotBeNull();
}

[Theory, MemberData(nameof(TestDatabaseProviders))]
Expand All @@ -292,7 +292,7 @@ public async Task FindByDeviceCodeAsync_WhenDeviceCodeDoesNotExist_ExpectNull(Db
{
var store = new DeviceFlowStore(context, new PersistentGrantSerializer(), FakeLogger<DeviceFlowStore>.Create(), new NoneCancellationTokenProvider());
var code = await store.FindByDeviceCodeAsync($"device_{Guid.NewGuid().ToString()}");
code.Should().BeNull();
code.ShouldBeNull();
}
}

Expand Down Expand Up @@ -351,15 +351,16 @@ public async Task UpdateByUserCodeAsync_WhenDeviceCodeAuthorized_ExpectSubjectAn
}

// should be unchanged
updatedCodes.DeviceCode.Should().Be(testDeviceCode);
updatedCodes.ClientId.Should().Be(unauthorizedDeviceCode.ClientId);
updatedCodes.CreationTime.Should().Be(unauthorizedDeviceCode.CreationTime);
updatedCodes.Expiration.Should().Be(unauthorizedDeviceCode.CreationTime.AddSeconds(authorizedDeviceCode.Lifetime));
updatedCodes.DeviceCode.ShouldBe(testDeviceCode);
updatedCodes.ClientId.ShouldBe(unauthorizedDeviceCode.ClientId);
updatedCodes.CreationTime.ShouldBe(unauthorizedDeviceCode.CreationTime);
updatedCodes.Expiration.ShouldBe(unauthorizedDeviceCode.CreationTime.AddSeconds(authorizedDeviceCode.Lifetime));

// should be changed
var parsedCode = serializer.Deserialize<DeviceCode>(updatedCodes.Data);
parsedCode.Should().BeEquivalentTo(authorizedDeviceCode, assertionOptions => assertionOptions.Excluding(x => x.Subject));
parsedCode.Subject.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject && x.Value == expectedSubject).Should().NotBeNull();
parsedCode.ShouldBe(authorizedDeviceCode);
//parsedCode.ShouldBeEquivalentTo(authorizedDeviceCode, assertionOptions => assertionOptions.Excluding(x => x.Subject));
parsedCode.Subject.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject && x.Value == expectedSubject).ShouldNotBeNull();
}

[Theory, MemberData(nameof(TestDatabaseProviders))]
Expand Down Expand Up @@ -399,7 +400,7 @@ public async Task RemoveByDeviceCodeAsync_WhenDeviceCodeExists_ExpectDeviceCodeD

using (var context = new PersistedGrantDbContext(options))
{
context.DeviceFlowCodes.FirstOrDefault(x => x.UserCode == testUserCode).Should().BeNull();
context.DeviceFlowCodes.FirstOrDefault(x => x.UserCode == testUserCode).ShouldBeNull();
}
}
[Theory, MemberData(nameof(TestDatabaseProviders))]
Expand Down
Loading

0 comments on commit cb3d63b

Please sign in to comment.