From efdd38bce84b5ac8d4aa54977603b265fb9d07f5 Mon Sep 17 00:00:00 2001 From: David Perfors Date: Tue, 11 Nov 2025 20:22:16 +0100 Subject: [PATCH 1/5] Add support for .NET 10 --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- .github/ISSUE_TEMPLATE/vulnerability.md | 2 +- .github/workflows/ci.yml | 4 +++- .github/workflows/codeql.yml | 1 + CHANGELOG.md | 1 + README.md | 1 + global.json | 4 ++-- src/TestableHttpClient/TestableHttpClient.csproj | 2 +- .../TestableHttpClient.IntegrationTests.csproj | 14 ++++++++++---- .../TestableHttpClient.Tests.csproj | 2 +- 10 files changed, 22 insertions(+), 11 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 49f397f..1298040 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -25,7 +25,7 @@ A clear and concise description of what you expected to happen. **Background (please complete the following information):** - Version of library: [e.g. 0.10] - - Version of .NET: [e.g. 8.0] + - Version of .NET: [e.g. 10.0] **Additional context** Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/vulnerability.md b/.github/ISSUE_TEMPLATE/vulnerability.md index a091826..abe0bfa 100644 --- a/.github/ISSUE_TEMPLATE/vulnerability.md +++ b/.github/ISSUE_TEMPLATE/vulnerability.md @@ -25,7 +25,7 @@ A clear and concise description of what you expected to happen. **Background (please complete the following information):** - Version of library: [e.g. 0.10] - - Version of .NET: [e.g. 7.0] + - Version of .NET: [e.g. 10.0] **Additional context** Add any other context about the vulnerability here. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 00c3286..29b27bd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,6 +29,7 @@ jobs: dotnet-version: | 8.0.x 9.0.x + 10.0.x - name: Dump .NET info run: dotnet --info - name: Restore dotnet tools @@ -80,6 +81,7 @@ jobs: dotnet-version: | 8.0.x 9.0.x + 10.0.x - name: Dump .NET info run: dotnet --info - name: Restore dependencies @@ -100,7 +102,7 @@ jobs: uses: actions/setup-dotnet@v4 with: dotnet-version: | - 9.0.x + 10.0.x - uses: actions/download-artifact@v4 with: name: artifacts diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index a9e509b..ff7ab25 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -28,6 +28,7 @@ jobs: dotnet-version: | 8.0.x 9.0.x + 10.0.x - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: diff --git a/CHANGELOG.md b/CHANGELOG.md index 958c300..05a1e8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - .NET Framework 4.6.2, 4.7.0 and 4.7.2, since these can't be tested using xUnit v3 ### Added - Support for .NET 9.0 +- support for .NET 10.0 ## [0.11] - 2024-06-15 ### Removed diff --git a/README.md b/README.md index 157bb5f..a408466 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,7 @@ The following versions are being actively tested and thus supported: - .NET Framework 4.7.2 and 4.8 - .NET 8.0 - .NET 9.0 +- .NET 10.0 These versions are supported as long as Microsoft supports them, we do our best to test and support newer versions as soon as possible. diff --git a/global.json b/global.json index 217f7c9..48b30cd 100644 --- a/global.json +++ b/global.json @@ -1,7 +1,7 @@ { "sdk": { - "version": "9.0.100", + "version": "10.0.100", "allowPrerelease": false, - "rollForward": "latestMajor" + "rollForward": "latestMinor" } } diff --git a/src/TestableHttpClient/TestableHttpClient.csproj b/src/TestableHttpClient/TestableHttpClient.csproj index 37d22ba..92913e0 100644 --- a/src/TestableHttpClient/TestableHttpClient.csproj +++ b/src/TestableHttpClient/TestableHttpClient.csproj @@ -1,7 +1,7 @@ - netstandard2.0;net8.0;net9.0 + netstandard2.0;net8.0;net9.0;net10.0 diff --git a/test/TestableHttpClient.IntegrationTests/TestableHttpClient.IntegrationTests.csproj b/test/TestableHttpClient.IntegrationTests/TestableHttpClient.IntegrationTests.csproj index 2053fe0..7b87905 100644 --- a/test/TestableHttpClient.IntegrationTests/TestableHttpClient.IntegrationTests.csproj +++ b/test/TestableHttpClient.IntegrationTests/TestableHttpClient.IntegrationTests.csproj @@ -1,7 +1,7 @@  - net472;net48;net8.0;net9.0 + net472;net48;net8.0;net9.0;net10.0 Exe @@ -17,9 +17,15 @@ - - - + + + + + + + + + diff --git a/test/TestableHttpClient.Tests/TestableHttpClient.Tests.csproj b/test/TestableHttpClient.Tests/TestableHttpClient.Tests.csproj index c501d52..62c2a35 100644 --- a/test/TestableHttpClient.Tests/TestableHttpClient.Tests.csproj +++ b/test/TestableHttpClient.Tests/TestableHttpClient.Tests.csproj @@ -1,7 +1,7 @@ - net472;net48;net8.0;net9.0 + net472;net48;net8.0;net9.0;net10.0 Exe From 419822d85688a1977537eacf6a2f92241dbc1a70 Mon Sep 17 00:00:00 2001 From: David Perfors Date: Tue, 11 Nov 2025 20:26:57 +0100 Subject: [PATCH 2/5] remove sonarqube scanning --- .config/dotnet-tools.json | 7 ------- .github/workflows/ci.yml | 16 ---------------- 2 files changed, 23 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index e7096cd..bc02258 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -2,13 +2,6 @@ "version": 1, "isRoot": true, "tools": { - "dotnet-sonarscanner": { - "version": "9.0.2", - "commands": [ - "dotnet-sonarscanner" - ], - "rollForward": false - }, "nbgv": { "version": "3.7.115", "commands": [ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 29b27bd..8011cb9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,11 +18,6 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 - - name: Update Java SDK for SonarQube - uses: actions/setup-java@v4 - with: - distribution: 'microsoft' - java-version: '21' - name: Setup .NET versions uses: actions/setup-dotnet@v4 with: @@ -34,23 +29,12 @@ jobs: run: dotnet --info - name: Restore dotnet tools run: dotnet tool restore - - name: Prepare sonarqube - if: ${{ github.actor != 'dependabot[bot]' }} - env: - SONAR_TOKEN: ${{secrets.SONAR_TOKEN}} - run: dotnet sonarscanner begin -d:sonar.host.url=https://sonarcloud.io -organization:testablehttpclient -key:testablehttpclient_TestableHttpClient -version:`dotnet nbgv get-version --variable NuGetPackageVersion` -d:sonar.cs.opencover.reportsPaths=**/coverage.opencover.xml -d:sonar.token=${{env.SONAR_TOKEN}} - name: Restore dependencies run: dotnet restore - name: Build source code run: dotnet build --configuration Release --no-restore - name: Test with dotnet run: dotnet test --configuration Release --no-build --collect="Code Coverage" --framework="net8.0" - - name: Upload sonarqube results - if: ${{ github.actor != 'dependabot[bot]' }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{secrets.SONAR_TOKEN}} - run: dotnet sonarscanner end -d:sonar.token=${{env.SONAR_TOKEN}} - name: Check source file format run: dotnet format --no-restore --verify-no-changes continue-on-error: true From 0c1e767e5c383f3f2819f698290506a0021fb318 Mon Sep 17 00:00:00 2001 From: David Perfors Date: Tue, 11 Nov 2025 20:39:35 +0100 Subject: [PATCH 3/5] Fix warnings and upgrade dotnet-tools --- .config/dotnet-tools.json | 2 +- .editorconfig | 3 +++ src/TestableHttpClient/IHttpRequestMessagesCheck.cs | 8 ++++---- src/TestableHttpClient/IResponse.cs | 2 +- src/TestableHttpClient/IRoutingResponseBuilder.cs | 4 ++-- src/TestableHttpClient/Response/RoutingResponse.cs | 1 + src/TestableHttpClient/TestableHttpClient.csproj | 1 - .../CustomizeJsonSerialization.cs | 12 ++++++++++++ .../Response/ResponseTestHelpers.cs | 8 ++++---- .../Utils/UriPatternParserTests.cs | 1 + 10 files changed, 29 insertions(+), 13 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index bc02258..a505d53 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "nbgv": { - "version": "3.7.115", + "version": "3.9.50", "commands": [ "nbgv" ], diff --git a/.editorconfig b/.editorconfig index d3fab62..cbaa220 100644 --- a/.editorconfig +++ b/.editorconfig @@ -94,3 +94,6 @@ dotnet_style_namespace_match_folder = true # CA1303: Do not pass literals as localized parameters dotnet_diagnostic.CA1303.severity = silent + +# IDE0060: Remove unused parameter +dotnet_diagnostic.IDE0060.severity = silent diff --git a/src/TestableHttpClient/IHttpRequestMessagesCheck.cs b/src/TestableHttpClient/IHttpRequestMessagesCheck.cs index 00bb341..d8faf81 100644 --- a/src/TestableHttpClient/IHttpRequestMessagesCheck.cs +++ b/src/TestableHttpClient/IHttpRequestMessagesCheck.cs @@ -8,7 +8,7 @@ public interface IHttpRequestMessagesCheck /// /// Options that could be used by several asserters. /// - TestableHttpMessageHandlerOptions Options { get; } + public TestableHttpMessageHandlerOptions Options { get; } /// /// Asserts whether requests comply with a specific filter. @@ -16,7 +16,7 @@ public interface IHttpRequestMessagesCheck /// The filter to filter requests with before asserting. /// The name of the condition, used in the exception message. /// The for further assertions. - IHttpRequestMessagesCheck WithFilter(Func requestFilter, string condition); + public IHttpRequestMessagesCheck WithFilter(Func requestFilter, string condition); /// /// Asserts whether requests comply with a specific filter. @@ -25,7 +25,7 @@ public interface IHttpRequestMessagesCheck /// The expected number of requests. /// The name of the condition, used in the exception message. /// The for further assertions. - IHttpRequestMessagesCheck WithFilter(Func requestFilter, int expectedNumberOfRequests, string condition); + public IHttpRequestMessagesCheck WithFilter(Func requestFilter, int expectedNumberOfRequests, string condition); /// /// Asserts whether requests comply with a specific filter. @@ -34,5 +34,5 @@ public interface IHttpRequestMessagesCheck /// The expected number of requests, when null is passed "at least one" is presumed. /// The name of the condition, used in the exception message. /// The for further assertions. - IHttpRequestMessagesCheck WithFilter(Func requestFilter, int? expectedNumberOfRequests, string condition); + public IHttpRequestMessagesCheck WithFilter(Func requestFilter, int? expectedNumberOfRequests, string condition); } diff --git a/src/TestableHttpClient/IResponse.cs b/src/TestableHttpClient/IResponse.cs index b3875fb..ff34a24 100644 --- a/src/TestableHttpClient/IResponse.cs +++ b/src/TestableHttpClient/IResponse.cs @@ -11,5 +11,5 @@ public interface IResponse /// The context for this request. /// The cancellationToken. /// - Task ExecuteAsync(HttpResponseContext context, CancellationToken cancellationToken); + public Task ExecuteAsync(HttpResponseContext context, CancellationToken cancellationToken); } diff --git a/src/TestableHttpClient/IRoutingResponseBuilder.cs b/src/TestableHttpClient/IRoutingResponseBuilder.cs index 2e4f6f4..a469fec 100644 --- a/src/TestableHttpClient/IRoutingResponseBuilder.cs +++ b/src/TestableHttpClient/IRoutingResponseBuilder.cs @@ -11,10 +11,10 @@ public interface IRoutingResponseBuilder /// The route pattern. /// The response the route should return. /// x.Map("*", Responses.StatusCode(HttpStatusCode.OK)) - void Map(string route, IResponse response); + public void Map(string route, IResponse response); /// /// Maps a custom response for when a request didn't match any route. Defaults to Responses.StatusCode(HttpStatusCode.NotFound). /// /// The response that should be returned when no route matches. - void MapFallBackResponse(IResponse fallBackResponse); + public void MapFallBackResponse(IResponse fallBackResponse); } diff --git a/src/TestableHttpClient/Response/RoutingResponse.cs b/src/TestableHttpClient/Response/RoutingResponse.cs index 7937daf..ee43fc6 100644 --- a/src/TestableHttpClient/Response/RoutingResponse.cs +++ b/src/TestableHttpClient/Response/RoutingResponse.cs @@ -2,6 +2,7 @@ using static TestableHttpClient.Responses; namespace TestableHttpClient.Response; + internal sealed class RoutingResponse : IResponse { public Task ExecuteAsync(HttpResponseContext context, CancellationToken cancellationToken) diff --git a/src/TestableHttpClient/TestableHttpClient.csproj b/src/TestableHttpClient/TestableHttpClient.csproj index 92913e0..d936fd0 100644 --- a/src/TestableHttpClient/TestableHttpClient.csproj +++ b/src/TestableHttpClient/TestableHttpClient.csproj @@ -32,7 +32,6 @@ - diff --git a/test/TestableHttpClient.IntegrationTests/CustomizeJsonSerialization.cs b/test/TestableHttpClient.IntegrationTests/CustomizeJsonSerialization.cs index 5c852b0..40d13bd 100644 --- a/test/TestableHttpClient.IntegrationTests/CustomizeJsonSerialization.cs +++ b/test/TestableHttpClient.IntegrationTests/CustomizeJsonSerialization.cs @@ -14,7 +14,11 @@ public async Task ByDefault_CamelCasing_is_used_for_json_serialization() sut.RespondWith(Json(new { Name = "Charlie" })); using HttpClient client = sut.CreateClient(); +#if NETFRAMEWORK string json = await client.GetStringAsync("http://localhost/myjson"); +#else + string json = await client.GetStringAsync("http://localhost/myjson", TestContext.Current.CancellationToken); +#endif Assert.Equal("{\"name\":\"Charlie\"}", json); } @@ -27,7 +31,11 @@ public async Task But_this_can_be_changed() sut.RespondWith(Json(new { Name = "Charlie" })); using HttpClient client = sut.CreateClient(); +#if NETFRAMEWORK string json = await client.GetStringAsync("http://localhost/myjson"); +#else + string json = await client.GetStringAsync("http://localhost/myjson", TestContext.Current.CancellationToken); +#endif Assert.Equal("{\"Name\":\"Charlie\"}", json); } @@ -39,7 +47,11 @@ public async Task But_Also_directly_on_the_response() sut.RespondWith(Json(new { Name = "Charlie" }, jsonSerializerOptions: new JsonSerializerOptions())); using HttpClient client = sut.CreateClient(); +#if NETFRAMEWORK string json = await client.GetStringAsync("http://localhost/myjson"); +#else + string json = await client.GetStringAsync("http://localhost/myjson", TestContext.Current.CancellationToken); +#endif Assert.Equal("{\"Name\":\"Charlie\"}", json); } diff --git a/test/TestableHttpClient.Tests/Response/ResponseTestHelpers.cs b/test/TestableHttpClient.Tests/Response/ResponseTestHelpers.cs index dc660f0..bf7c880 100644 --- a/test/TestableHttpClient.Tests/Response/ResponseTestHelpers.cs +++ b/test/TestableHttpClient.Tests/Response/ResponseTestHelpers.cs @@ -3,17 +3,17 @@ internal static class ResponseTestHelpers { public static Task TestAsync(this IResponse response) => TestAsync(response, "http://httpbin.org"); - public static Task TestAsync(this IResponse response, string url) + public static async Task TestAsync(this IResponse response, string url) { using TestableHttpMessageHandler handler = new(); handler.RespondWith(response); - return handler.TestAsync(url); + return await handler.TestAsync(url); } public static Task TestAsync(this TestableHttpMessageHandler handler) => TestAsync(handler, "http://httpbin.org"); - public static Task TestAsync(this TestableHttpMessageHandler handler, string url) + public static async Task TestAsync(this TestableHttpMessageHandler handler, string url) { using HttpClient client = new(handler); - return client.GetAsync(url); + return await client.GetAsync(url); } } diff --git a/test/TestableHttpClient.Tests/Utils/UriPatternParserTests.cs b/test/TestableHttpClient.Tests/Utils/UriPatternParserTests.cs index 696274a..54f1aed 100644 --- a/test/TestableHttpClient.Tests/Utils/UriPatternParserTests.cs +++ b/test/TestableHttpClient.Tests/Utils/UriPatternParserTests.cs @@ -1,6 +1,7 @@ using TestableHttpClient.Utils; namespace TestableHttpClient.Tests.Utils; + public class UriPatternParserTests { [Theory] From 9400fb76f8d8908f35e57a4fe79ea995501c60fc Mon Sep 17 00:00:00 2001 From: David Perfors Date: Tue, 11 Nov 2025 20:45:18 +0100 Subject: [PATCH 4/5] Upgrade packages --- src/TestableHttpClient/TestableHttpClient.csproj | 2 +- test/Directory.Build.targets | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/TestableHttpClient/TestableHttpClient.csproj b/src/TestableHttpClient/TestableHttpClient.csproj index d936fd0..35bea58 100644 --- a/src/TestableHttpClient/TestableHttpClient.csproj +++ b/src/TestableHttpClient/TestableHttpClient.csproj @@ -43,7 +43,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/test/Directory.Build.targets b/test/Directory.Build.targets index 6348ff4..fb53bb9 100644 --- a/test/Directory.Build.targets +++ b/test/Directory.Build.targets @@ -1,7 +1,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive From 5d29972909b4858a1ea444bc0f3e9cf96d0344c6 Mon Sep 17 00:00:00 2001 From: David Perfors Date: Tue, 11 Nov 2025 21:59:38 +0100 Subject: [PATCH 5/5] Use new testing platform --- .github/workflows/ci.yml | 6 +----- test/Directory.Build.props | 3 ++- test/Directory.Build.targets | 9 --------- test/coverlet.runsettings | 14 -------------- 4 files changed, 3 insertions(+), 29 deletions(-) delete mode 100644 test/coverlet.runsettings diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8011cb9..e061547 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: - name: Build source code run: dotnet build --configuration Release --no-restore - name: Test with dotnet - run: dotnet test --configuration Release --no-build --collect="Code Coverage" --framework="net8.0" + run: dotnet test --configuration Release --no-build --framework="net8.0" - name: Check source file format run: dotnet format --no-restore --verify-no-changes continue-on-error: true @@ -44,10 +44,6 @@ jobs: with: name: artifacts path: ./artifacts - - uses: actions/upload-artifact@v4 - with: - name: coverage - path: ./**/TestResults/**/coverage.opencover.xml testOnSupportedDotnetVersions: strategy: diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 9f5616b..ac1b91f 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -2,7 +2,8 @@ false - $(MSBuildThisFileDirectory)/coverlet.runsettings + true + true diff --git a/test/Directory.Build.targets b/test/Directory.Build.targets index fb53bb9..69c311b 100644 --- a/test/Directory.Build.targets +++ b/test/Directory.Build.targets @@ -1,14 +1,5 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/test/coverlet.runsettings b/test/coverlet.runsettings deleted file mode 100644 index 1d4e323..0000000 --- a/test/coverlet.runsettings +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - opencover - GeneratedCodeAttribute,CompilerGeneratedAttribute - false - - - - - \ No newline at end of file