From 02c744b2e4317259665db4898471ed4ecb479a0d Mon Sep 17 00:00:00 2001 From: Eric Sibly Date: Fri, 17 May 2024 14:09:25 -0700 Subject: [PATCH] HttpClient mock tracing. --- CHANGELOG.md | 3 +++ Common.targets | 2 +- src/UnitTestEx/Mocking/MockHttpClient.cs | 21 +++++++++++++++++++ .../Mocking/MockHttpClientRequest.cs | 2 +- .../MockHttpClientTest.cs | 16 ++++++++++++++ 5 files changed, 42 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 358e2ab..285d767 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ Represents the **NuGet** versions. +## v4.3.2 +- *Fixed*: Added `TraceRequestComparisons` support to `MockHttpClient` to enable tracing for all requests. + ## v4.3.1 - *Fixed*: Added `StringSyntaxAttribute` support to improve intellisense for JSON and URI specification. diff --git a/Common.targets b/Common.targets index 8d9db7e..d6dcedd 100644 --- a/Common.targets +++ b/Common.targets @@ -1,6 +1,6 @@  - 4.3.1 + 4.3.2 preview Avanade Avanade diff --git a/src/UnitTestEx/Mocking/MockHttpClient.cs b/src/UnitTestEx/Mocking/MockHttpClient.cs index 18aa345..b8cdaeb 100644 --- a/src/UnitTestEx/Mocking/MockHttpClient.cs +++ b/src/UnitTestEx/Mocking/MockHttpClient.cs @@ -35,6 +35,7 @@ public sealed class MockHttpClient : IDisposable private bool _useHttpMessageHandlers; private Type[] _excludeTypes = []; private bool _useHttpClientConfigurations; + private bool _traceRequestComparisons; /// /// Initializes a new instance of the class. @@ -249,9 +250,29 @@ public MockHttpClientRequest Request(HttpMethod? method = null, string? requestU var r = new MockHttpClientRequest(this, method ?? HttpMethod.Get, requestUri); _requests.Add(r); + if (_traceRequestComparisons) + r.TraceRequestComparisons(); + return r; } + /// + /// Indicates whether the request content comparison differences should be trace logged to aid in debugging/troubleshooting. + /// + /// The to support fluent-style method-chaining. + /// By default the request content comparison differences are not traced. Where tracing is requested all existing and new configurations + /// will be traced. + public MockHttpClient TraceRequestComparisons() + { + _traceRequestComparisons = true; + foreach (var r in _requests) + { + r.TraceRequestComparisons(); + } + + return this; + } + /// /// Verifies that all verifiable expectations have been met; being all requests have been invoked. /// diff --git a/src/UnitTestEx/Mocking/MockHttpClientRequest.cs b/src/UnitTestEx/Mocking/MockHttpClientRequest.cs index 3f0567c..5b62174 100644 --- a/src/UnitTestEx/Mocking/MockHttpClientRequest.cs +++ b/src/UnitTestEx/Mocking/MockHttpClientRequest.cs @@ -189,7 +189,7 @@ private bool RequestPredicate(HttpRequestMessage request) options.JsonSerializer ??= JsonSerializer; var jcr = new JsonElementComparer(options).Compare(content, body, _pathsToIgnore); if (jcr.HasDifferences && _traceRequestComparisons) - Implementor.WriteLine($"HTTP request JsonElementComparer differences:{Environment.NewLine}{jcr}"); + Implementor.WriteLine($"UnitTestEx > Mismatched HTTP request {request.Method} {request.RequestUri} mocked vs actual trace comparison differences:{Environment.NewLine}{jcr}"); return jcr.AreEqual; } diff --git a/tests/UnitTestEx.MSTest.Test/MockHttpClientTest.cs b/tests/UnitTestEx.MSTest.Test/MockHttpClientTest.cs index 882ecb9..b1cb7db 100644 --- a/tests/UnitTestEx.MSTest.Test/MockHttpClientTest.cs +++ b/tests/UnitTestEx.MSTest.Test/MockHttpClientTest.cs @@ -134,6 +134,22 @@ public async Task UriAndBody_Json_Multi() Assert.AreEqual(HttpStatusCode.OK, res.StatusCode); } + [TestMethod] + public async Task UriAndBody_Json_Multi2() + { + var mcf = MockHttpClientFactory.Create(); + var mc = mcf.CreateClient("XXX", new Uri("https://d365test")).TraceRequestComparisons(); + mc.Request(HttpMethod.Post, "products/xyz").WithJsonBody("{\"firstName\":\"Bob\",\"lastName\":\"Jane\"}").Respond.With(HttpStatusCode.Accepted); + mc.Request(HttpMethod.Post, "products/xyz").WithJsonBody(new Person { FirstName = "Jenny", LastName = "Browne" }).Respond.With(HttpStatusCode.OK); + + var hc = mcf.GetHttpClient("XXX"); + var res = await hc.PostAsJsonAsync("products/xyz", new Person { LastName = "Jane", FirstName = "Bob" }).ConfigureAwait(false); + Assert.AreEqual(HttpStatusCode.Accepted, res.StatusCode); + + res = await hc.PostAsync("products/xyz", new StringContent("{\"firstName\":\"Jenny\",\"lastName\":\"Browne\"}", Encoding.UTF8, MediaTypeNames.Application.Json)).ConfigureAwait(false); + Assert.AreEqual(HttpStatusCode.OK, res.StatusCode); + } + [TestMethod] public async Task UriAndBody_WithJsonResponse() {