diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 35ad301b6..3ebd41d34 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,9 @@ jobs: - uses: actions/checkout@v4 - name: 'Execute Tests' - run: dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0 + run: | + dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0 + dotnet test './test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj' -c Release --framework net8.0 linux-build-and-run: name: Run Tests on Linux @@ -33,7 +35,9 @@ jobs: - uses: actions/checkout@v4 - name: 'Execute Tests' - run: dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0 + run: | + dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0 + dotnet test './test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj' -c Release --framework net8.0 - name: Install .NET Aspire workload run: dotnet workload install aspire diff --git a/WireMock.Net Solution.sln b/WireMock.Net Solution.sln index c262e192a..98ae19beb 100644 --- a/WireMock.Net Solution.sln +++ b/WireMock.Net Solution.sln @@ -131,6 +131,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Aspire.TestApp EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspireApp1.AppHostOriginal", "examples-Aspire\AspireApp1.AppHostOriginal\AspireApp1.AppHostOriginal.csproj", "{C9210DA3-F390-4598-8512-349A473FE9C9}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.TUnit", "src\WireMock.Net.TUnit\WireMock.Net.TUnit.csproj", "{91024A93-848F-4A02-AF53-5EBE5834E23C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.TUnitTests", "test\WireMock.Net.TUnitTests\WireMock.Net.TUnitTests.csproj", "{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -317,6 +321,14 @@ Global {C9210DA3-F390-4598-8512-349A473FE9C9}.Debug|Any CPU.Build.0 = Debug|Any CPU {C9210DA3-F390-4598-8512-349A473FE9C9}.Release|Any CPU.ActiveCfg = Release|Any CPU {C9210DA3-F390-4598-8512-349A473FE9C9}.Release|Any CPU.Build.0 = Release|Any CPU + {91024A93-848F-4A02-AF53-5EBE5834E23C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {91024A93-848F-4A02-AF53-5EBE5834E23C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {91024A93-848F-4A02-AF53-5EBE5834E23C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {91024A93-848F-4A02-AF53-5EBE5834E23C}.Release|Any CPU.Build.0 = Release|Any CPU + {4CD237F7-B616-46B8-872F-E49B4BBB3EAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4CD237F7-B616-46B8-872F-E49B4BBB3EAE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4CD237F7-B616-46B8-872F-E49B4BBB3EAE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4CD237F7-B616-46B8-872F-E49B4BBB3EAE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -369,6 +381,8 @@ Global {CE602F57-FEF8-4559-A9E0-6200BE1BF398} = {0BB8B634-407A-4610-A91F-11586990767A} {F1B5999D-D22E-48A6-AB86-18A7876BD32E} = {0BB8B634-407A-4610-A91F-11586990767A} {C9210DA3-F390-4598-8512-349A473FE9C9} = {AD474543-0715-49F2-A284-936B060BF736} + {91024A93-848F-4A02-AF53-5EBE5834E23C} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2} + {4CD237F7-B616-46B8-872F-E49B4BBB3EAE} = {0BB8B634-407A-4610-A91F-11586990767A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458} diff --git a/azure-pipelines-ci.yml b/azure-pipelines-ci.yml index 834ef5b20..3b2523fc9 100644 --- a/azure-pipelines-ci.yml +++ b/azure-pipelines-ci.yml @@ -38,7 +38,7 @@ jobs: # See: https://docs.sonarsource.com/sonarcloud/enriching/test-coverage/dotnet-test-coverage - script: | - dotnet sonarscanner begin /k:"WireMock-Net_WireMock.Net" /o:"wiremock-net" /d:sonar.branch.name=$(Build.SourceBranchName) /d:sonar.host.url="https://sonarcloud.io" /d:sonar.token="$(SONAR_TOKEN)" /d:sonar.pullrequest.provider=github /d:sonar.dotnet.excludeTestProjects=true /d:sonar.cs.vscoveragexml.reportsPaths=**/wiremock-coverage-*.xml /d:sonar.verbose=true + dotnet sonarscanner begin /k:"WireMock-Net_WireMock.Net" /o:"wiremock-net" /d:sonar.branch.name=$(Build.SourceBranchName) /d:sonar.host.url="https://sonarcloud.io" /d:sonar.token="$(SONAR_TOKEN)" /d:sonar.pullrequest.provider=github /d:sonar.cs.vscoveragexml.reportsPaths=**/wiremock-coverage-*.xml /d:sonar.verbose=true displayName: 'Begin analysis on SonarCloud' condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests @@ -52,13 +52,14 @@ jobs: - task: CmdLine@2 inputs: script: | - dotnet-coverage collect "dotnet test ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --configuration Debug --no-build --framework net8.0" -f xml -o "wiremock-coverage-1.xml" - displayName: 'Execute WireMock.Net.Tests with Coverage' + dotnet-coverage collect "dotnet test ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --configuration Debug --no-build --framework net8.0" -f xml -o "wiremock-coverage-xunit.xml" + dotnet-coverage collect "dotnet test ./test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj --configuration Debug --no-build --framework net8.0" -f xml -o "wiremock-coverage-tunit.xml" + displayName: 'Execute WireMock.Net.Tests with Coverage' - task: CmdLine@2 inputs: script: | - dotnet-coverage collect "dotnet test ./test/WireMock.Net.Aspire.Tests/WireMock.Net.Aspire.Tests.csproj --configuration Debug --no-build" -f xml -o "wiremock-coverage-2.xml" + dotnet-coverage collect "dotnet test ./test/WireMock.Net.Aspire.Tests/WireMock.Net.Aspire.Tests.csproj --configuration Debug --no-build" -f xml -o "wiremock-coverage-aspire.xml" displayName: 'Execute WireMock.Net.Aspire.Tests with Coverage' - task: CmdLine@2 diff --git a/src/WireMock.Net.TUnit/TUnitWireMockLogger.cs b/src/WireMock.Net.TUnit/TUnitWireMockLogger.cs new file mode 100644 index 000000000..a38926004 --- /dev/null +++ b/src/WireMock.Net.TUnit/TUnitWireMockLogger.cs @@ -0,0 +1,80 @@ +// Copyright © WireMock.Net + +using System; +using Newtonsoft.Json; +using Stef.Validation; +using TUnit.Core.Logging; +using WireMock.Admin.Requests; +using WireMock.Logging; + +namespace WireMock.Net.TUnit; + +/// +/// When using TUnit, this class enables to log the output from WireMock.Net to the . +/// +// ReSharper disable once InconsistentNaming +public sealed class TUnitWireMockLogger : IWireMockLogger +{ + private readonly TUnitLogger _tUnitLogger; + + /// + /// Create a new instance on the . + /// + /// Represents a class which can be used to provide test output. + public TUnitWireMockLogger(TUnitLogger tUnitLogger) + { + _tUnitLogger = Guard.NotNull(tUnitLogger); + } + + /// + public void Debug(string formatString, params object[] args) + { + _tUnitLogger.LogDebug(Format("Debug", formatString, args)); + } + + /// + public void Info(string formatString, params object[] args) + { + _tUnitLogger.LogInformation(Format("Info", formatString, args)); + } + + /// + public void Warn(string formatString, params object[] args) + { + _tUnitLogger.LogWarning(Format("Warning", formatString, args)); + } + + /// + public void Error(string formatString, params object[] args) + { + _tUnitLogger.LogError(Format("Error", formatString, args)); + } + + /// + public void Error(string formatString, Exception exception) + { + _tUnitLogger.LogError(Format("Error", formatString, exception.Message), exception); + + if (exception is AggregateException ae) + { + ae.Handle(ex => + { + _tUnitLogger.LogError(Format("Error", "Exception {0}", ex.Message), exception); + return true; + }); + } + } + + /// + public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminRequest) + { + var message = JsonConvert.SerializeObject(logEntryModel, Formatting.Indented); + _tUnitLogger.LogDebug(Format("DebugRequestResponse", "Admin[{0}] {1}", isAdminRequest, message)); + } + + private static string Format(string level, string formatString, params object[] args) + { + var message = args.Length > 0 ? string.Format(formatString, args) : formatString; + return $"{DateTime.UtcNow} [{level}] : {message}"; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.TUnit/WireMock.Net.TUnit.csproj b/src/WireMock.Net.TUnit/WireMock.Net.TUnit.csproj new file mode 100644 index 000000000..47c9c3c44 --- /dev/null +++ b/src/WireMock.Net.TUnit/WireMock.Net.TUnit.csproj @@ -0,0 +1,38 @@ + + + + Some extensions for TUnit (TUnitLogger) + WireMock.Net.TUnit + Stef Heyenrath + net8.0 + true + WireMock.Net.TUnit + WireMock.Net.Tunit + WireMock.Net.TUnit + tdd;wiremock;test;unittest;TUnit + {0DE0954F-8C00-4E8D-B94A-4361FC1CB34A} + true + $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb + true + true + true + true + ../WireMock.Net/WireMock.Net.snk + true + + + + true + + + + + + + + + + + + + diff --git a/src/WireMock.Net.xUnit/TestOutputHelperWireMockLogger.cs b/src/WireMock.Net.xUnit/TestOutputHelperWireMockLogger.cs index 51570e8e3..df83bac37 100644 --- a/src/WireMock.Net.xUnit/TestOutputHelperWireMockLogger.cs +++ b/src/WireMock.Net.xUnit/TestOutputHelperWireMockLogger.cs @@ -73,8 +73,6 @@ public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminReques private static string Format(string level, string formatString, params object[] args) { - Guard.NotNull(formatString); - var message = args.Length > 0 ? string.Format(formatString, args) : formatString; return $"{DateTime.UtcNow} [{level}] : {message}"; } diff --git a/test/WireMock.Net.TUnitTests/TUnitTests.cs b/test/WireMock.Net.TUnitTests/TUnitTests.cs new file mode 100644 index 000000000..fd5ef881b --- /dev/null +++ b/test/WireMock.Net.TUnitTests/TUnitTests.cs @@ -0,0 +1,37 @@ +// Copyright © WireMock.Net + +using WireMock.Net.TUnit; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using WireMock.Server; +using WireMock.Settings; + +namespace WireMock.Net.TUnitTests; + +// ReSharper disable once InconsistentNaming +public class TUnitTests +{ + [Test] + public async Task Test_TUnitWireMockLogger() + { + // Assign + var path = $"/foo_{Guid.NewGuid()}"; + + using var server = WireMockServer.Start(new WireMockServerSettings + { + Logger = new TUnitWireMockLogger(TestContext.Current!.GetDefaultLogger()) + }); + + server + .Given(Request.Create() + .WithPath(path) + .UsingGet()) + .RespondWith(Response.Create().WithBody("TUnit")); + + // Act + var response = await server.CreateClient().GetStringAsync($"{server.Url}{path}"); + + // Assert + await Assert.That(response).IsEqualTo("TUnit"); + } +} \ No newline at end of file diff --git a/test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj b/test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj new file mode 100644 index 000000000..38793c054 --- /dev/null +++ b/test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj @@ -0,0 +1,18 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + +