diff --git a/src/WireMock.Net.Minimal/Owin/IWireMockMiddlewareOptions.cs b/src/WireMock.Net.Minimal/Owin/IWireMockMiddlewareOptions.cs index 59c3a237..9bbf47fe 100644 --- a/src/WireMock.Net.Minimal/Owin/IWireMockMiddlewareOptions.cs +++ b/src/WireMock.Net.Minimal/Owin/IWireMockMiddlewareOptions.cs @@ -2,6 +2,7 @@ using System.Collections.Concurrent; using System.Security.Cryptography.X509Certificates; +using JsonConverter.Abstractions; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using WireMock.Handlers; @@ -99,4 +100,12 @@ internal interface IWireMockMiddlewareOptions /// WebSocket settings. /// WebSocketSettings? WebSocketSettings { get; set; } + + /// + /// Gets or sets the default JSON converter used for serialization. + /// + /// + /// Set this property to customize how objects are serialized to and deserialized from JSON during mapping. + /// + IJsonConverter DefaultJsonSerializer { get; set; } } \ No newline at end of file diff --git a/src/WireMock.Net.Minimal/Owin/Mappers/OwinResponseMapper.cs b/src/WireMock.Net.Minimal/Owin/Mappers/OwinResponseMapper.cs index 170960e7..8dc60798 100644 --- a/src/WireMock.Net.Minimal/Owin/Mappers/OwinResponseMapper.cs +++ b/src/WireMock.Net.Minimal/Owin/Mappers/OwinResponseMapper.cs @@ -3,249 +3,242 @@ using System.Globalization; using System.Net; using System.Text; +using JsonConverter.Abstractions; using Microsoft.AspNetCore.Http; -using Newtonsoft.Json; using RandomDataGenerator.FieldOptions; using RandomDataGenerator.Randomizers; -using Stef.Validation; using WireMock.Http; using WireMock.ResponseBuilders; using WireMock.ResponseProviders; using WireMock.Types; using WireMock.Util; -namespace WireMock.Owin.Mappers +namespace WireMock.Owin.Mappers; + +/// +/// OwinResponseMapper +/// +internal class OwinResponseMapper(IWireMockMiddlewareOptions options) : IOwinResponseMapper { - /// - /// OwinResponseMapper - /// - internal class OwinResponseMapper : IOwinResponseMapper + private readonly IRandomizerNumber _randomizerDouble = RandomizerFactory.GetRandomizer(new FieldOptionsDouble { Min = 0, Max = 1 }); + private readonly IRandomizerBytes _randomizerBytes = RandomizerFactory.GetRandomizer(new FieldOptionsBytes { Min = 100, Max = 200 }); + private readonly Encoding _utf8NoBom = new UTF8Encoding(false); + + // https://msdn.microsoft.com/en-us/library/78h415ay(v=vs.110).aspx + private static readonly IDictionary>> ResponseHeadersToFix = + new Dictionary>>(StringComparer.OrdinalIgnoreCase) + { + { HttpKnownHeaderNames.ContentType, (r, _, v) => r.ContentType = v.FirstOrDefault() }, + { HttpKnownHeaderNames.ContentLength, (r, hasBody, v) => + { + // Only set the Content-Length header if the response does not have a body + if (!hasBody && long.TryParse(v.FirstOrDefault(), out var contentLength)) + { + r.ContentLength = contentLength; + } + } + } + }; + + /// + public async Task MapAsync(IResponseMessage? responseMessage, HttpResponse response) { - private readonly IRandomizerNumber _randomizerDouble = RandomizerFactory.GetRandomizer(new FieldOptionsDouble { Min = 0, Max = 1 }); - private readonly IRandomizerBytes _randomizerBytes = RandomizerFactory.GetRandomizer(new FieldOptionsBytes { Min = 100, Max = 200 }); - private readonly IWireMockMiddlewareOptions _options; - private readonly Encoding _utf8NoBom = new UTF8Encoding(false); - - // https://msdn.microsoft.com/en-us/library/78h415ay(v=vs.110).aspx - private static readonly IDictionary>> ResponseHeadersToFix = - new Dictionary>>(StringComparer.OrdinalIgnoreCase) - { - { HttpKnownHeaderNames.ContentType, (r, _, v) => r.ContentType = v.FirstOrDefault() }, - { HttpKnownHeaderNames.ContentLength, (r, hasBody, v) => - { - // Only set the Content-Length header if the response does not have a body - if (!hasBody && long.TryParse(v.FirstOrDefault(), out var contentLength)) - { - r.ContentLength = contentLength; - } - } - } - }; - - /// - /// Constructor - /// - /// The IWireMockMiddlewareOptions. - public OwinResponseMapper(IWireMockMiddlewareOptions options) + if (responseMessage == null || responseMessage is WebSocketHandledResponse) { - _options = Guard.NotNull(options); + return; } - /// - public async Task MapAsync(IResponseMessage? responseMessage, HttpResponse response) + var bodyData = responseMessage.BodyData; + if (bodyData?.GetDetectedBodyType() == BodyType.SseString) { - if (responseMessage == null || responseMessage is WebSocketHandledResponse) - { - return; - } + await HandleSseStringAsync(responseMessage, response, bodyData); + return; + } - var bodyData = responseMessage.BodyData; - if (bodyData?.GetDetectedBodyType() == BodyType.SseString) - { - await HandleSseStringAsync(responseMessage, response, bodyData); - return; - } + byte[]? bytes; + switch (responseMessage.FaultType) + { + case FaultType.EMPTY_RESPONSE: + bytes = IsFault(responseMessage) ? [] : await GetNormalBodyAsync(responseMessage).ConfigureAwait(false); + break; - byte[]? bytes; - switch (responseMessage.FaultType) - { - case FaultType.EMPTY_RESPONSE: - bytes = IsFault(responseMessage) ? [] : await GetNormalBodyAsync(responseMessage).ConfigureAwait(false); - break; - - case FaultType.MALFORMED_RESPONSE_CHUNK: - bytes = await GetNormalBodyAsync(responseMessage).ConfigureAwait(false) ?? []; - if (IsFault(responseMessage)) - { - bytes = bytes.Take(bytes.Length / 2).Union(_randomizerBytes.Generate()).ToArray(); - } - break; - - default: - bytes = await GetNormalBodyAsync(responseMessage).ConfigureAwait(false); - break; - } - - if (responseMessage.StatusCode is HttpStatusCode or int) - { - response.StatusCode = MapStatusCode((int) responseMessage.StatusCode); - } - else if (responseMessage.StatusCode is string statusCodeAsString) - { - // Note: this case will also match on null - _ = int.TryParse(statusCodeAsString, out var statusCodeTypeAsInt); - response.StatusCode = MapStatusCode(statusCodeTypeAsInt); - } - - SetResponseHeaders(responseMessage, bytes != null, response); - - if (bytes != null) - { - try + case FaultType.MALFORMED_RESPONSE_CHUNK: + bytes = await GetNormalBodyAsync(responseMessage).ConfigureAwait(false) ?? []; + if (IsFault(responseMessage)) { - await response.Body.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); + bytes = bytes.Take(bytes.Length / 2).Union(_randomizerBytes.Generate()).ToArray(); } - catch (Exception ex) + break; + + default: + bytes = await GetNormalBodyAsync(responseMessage).ConfigureAwait(false); + break; + } + + if (responseMessage.StatusCode is HttpStatusCode or int) + { + response.StatusCode = MapStatusCode((int)responseMessage.StatusCode); + } + else if (responseMessage.StatusCode is string statusCodeAsString) + { + // Note: this case will also match on null + _ = int.TryParse(statusCodeAsString, out var statusCodeTypeAsInt); + response.StatusCode = MapStatusCode(statusCodeTypeAsInt); + } + + SetResponseHeaders(responseMessage, bytes != null, response); + + if (bytes != null) + { + try + { + await response.Body.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); + } + catch (Exception ex) + { + options.Logger.Warn("Error writing response body. Exception : {0}", ex); + } + } + + SetResponseTrailingHeaders(responseMessage, response); + } + + private static async Task HandleSseStringAsync(IResponseMessage responseMessage, HttpResponse response, IBodyData bodyData) + { + if (bodyData.SseStringQueue == null) + { + return; + } + + SetResponseHeaders(responseMessage, true, response); + + string? text; + do + { + if (bodyData.SseStringQueue.TryRead(out text)) + { + await response.WriteAsync(text); + await response.Body.FlushAsync(); + } + } while (text != null); + } + + private int MapStatusCode(int code) + { + if (options.AllowOnlyDefinedHttpStatusCodeInResponse == true && !Enum.IsDefined(typeof(HttpStatusCode), code)) + { + return (int)HttpStatusCode.OK; + } + + return code; + } + + private bool IsFault(IResponseMessage responseMessage) + { + return responseMessage.FaultPercentage == null || _randomizerDouble.Generate() <= responseMessage.FaultPercentage; + } + + private async Task GetNormalBodyAsync(IResponseMessage responseMessage) + { + var bodyData = responseMessage.BodyData; + switch (bodyData?.GetDetectedBodyType()) + { + case BodyType.String: + case BodyType.FormUrlEncoded: + return (bodyData.Encoding ?? _utf8NoBom).GetBytes(bodyData.BodyAsString!); + + case BodyType.Json: + var jsonConverterOptions = new JsonConverterOptions { - _options.Logger.Warn("Error writing response body. Exception : {0}", ex); - } - } + WriteIndented = bodyData.BodyAsJsonIndented == true, + IgnoreNullValues = true + }; - SetResponseTrailingHeaders(responseMessage, response); - } + var jsonBody = options.DefaultJsonSerializer.Serialize(bodyData.BodyAsJson!, jsonConverterOptions); + return (bodyData.Encoding ?? _utf8NoBom).GetBytes(jsonBody); - private static async Task HandleSseStringAsync(IResponseMessage responseMessage, HttpResponse response, IBodyData bodyData) - { - if (bodyData.SseStringQueue == null) - { - return; - } - - SetResponseHeaders(responseMessage, true, response); - - string? text; - do - { - if (bodyData.SseStringQueue.TryRead(out text)) + case BodyType.ProtoBuf: + if (TypeLoader.TryLoadStaticInstance(out var protoBufUtils)) { - await response.WriteAsync(text); - await response.Body.FlushAsync(); + var protoDefinitions = bodyData.ProtoDefinition?.Invoke().Texts; + return await protoBufUtils.GetProtoBufMessageWithHeaderAsync(protoDefinitions, bodyData.ProtoBufMessageType, bodyData.BodyAsJson).ConfigureAwait(false); } - } while (text != null); + break; + + case BodyType.Bytes: + return bodyData.BodyAsBytes; + + case BodyType.File: + return options.FileSystemHandler?.ReadResponseBodyAsFile(bodyData.BodyAsFile!); + + case BodyType.MultiPart: + options.Logger.Warn("MultiPart body type is not handled!"); + break; + + case BodyType.None: + break; } - private int MapStatusCode(int code) + return null; + } + + private static void SetResponseHeaders(IResponseMessage responseMessage, bool hasBody, HttpResponse response) + { + // Force setting the Date header (#577) + AppendResponseHeader( + response, + HttpKnownHeaderNames.Date, + [DateTime.UtcNow.ToString(CultureInfo.InvariantCulture.DateTimeFormat.RFC1123Pattern, CultureInfo.InvariantCulture)] + ); + + // Set other headers + foreach (var item in responseMessage.Headers!) { - if (_options.AllowOnlyDefinedHttpStatusCodeInResponse == true && !Enum.IsDefined(typeof(HttpStatusCode), code)) + var headerName = item.Key; + var value = item.Value; + if (ResponseHeadersToFix.TryGetValue(headerName, out var action)) { - return (int)HttpStatusCode.OK; + action.Invoke(response, hasBody, value); } - - return code; - } - - private bool IsFault(IResponseMessage responseMessage) - { - return responseMessage.FaultPercentage == null || _randomizerDouble.Generate() <= responseMessage.FaultPercentage; - } - - private async Task GetNormalBodyAsync(IResponseMessage responseMessage) - { - var bodyData = responseMessage.BodyData; - switch (bodyData?.GetDetectedBodyType()) + else { - case BodyType.String: - case BodyType.FormUrlEncoded: - return (bodyData.Encoding ?? _utf8NoBom).GetBytes(bodyData.BodyAsString!); - - case BodyType.Json: - var formatting = bodyData.BodyAsJsonIndented == true ? Formatting.Indented : Formatting.None; - var jsonBody = JsonConvert.SerializeObject(bodyData.BodyAsJson, new JsonSerializerSettings { Formatting = formatting, NullValueHandling = NullValueHandling.Ignore }); - return (bodyData.Encoding ?? _utf8NoBom).GetBytes(jsonBody); - - case BodyType.ProtoBuf: - if (TypeLoader.TryLoadStaticInstance(out var protoBufUtils)) - { - var protoDefinitions = bodyData.ProtoDefinition?.Invoke().Texts; - return await protoBufUtils.GetProtoBufMessageWithHeaderAsync(protoDefinitions, bodyData.ProtoBufMessageType, bodyData.BodyAsJson).ConfigureAwait(false); - } - break; - - case BodyType.Bytes: - return bodyData.BodyAsBytes; - - case BodyType.File: - return _options.FileSystemHandler?.ReadResponseBodyAsFile(bodyData.BodyAsFile!); - - case BodyType.MultiPart: - _options.Logger.Warn("MultiPart body type is not handled!"); - break; - - case BodyType.None: - break; - } - - return null; - } - - private static void SetResponseHeaders(IResponseMessage responseMessage, bool hasBody, HttpResponse response) - { - // Force setting the Date header (#577) - AppendResponseHeader( - response, - HttpKnownHeaderNames.Date, - [DateTime.UtcNow.ToString(CultureInfo.InvariantCulture.DateTimeFormat.RFC1123Pattern, CultureInfo.InvariantCulture)] - ); - - // Set other headers - foreach (var item in responseMessage.Headers!) - { - var headerName = item.Key; - var value = item.Value; - if (ResponseHeadersToFix.TryGetValue(headerName, out var action)) + // Check if this response header can be added (#148, #227 and #720) + if (!HttpKnownHeaderNames.IsRestrictedResponseHeader(headerName)) { - action.Invoke(response, hasBody, value); - } - else - { - // Check if this response header can be added (#148, #227 and #720) - if (!HttpKnownHeaderNames.IsRestrictedResponseHeader(headerName)) - { - AppendResponseHeader(response, headerName, value.ToArray()); - } + AppendResponseHeader(response, headerName, value.ToArray()); } } } - - private static void SetResponseTrailingHeaders(IResponseMessage responseMessage, HttpResponse response) - { - if (responseMessage.TrailingHeaders == null) - { - return; - } - -#if TRAILINGHEADERS - foreach (var (headerName, value) in responseMessage.TrailingHeaders) - { - if (ResponseHeadersToFix.TryGetValue(headerName, out var action)) - { - action.Invoke(response, false, value); - } - else - { - // Check if this trailing header can be added to the response - if (response.SupportsTrailers() && !HttpKnownHeaderNames.IsRestrictedResponseHeader(headerName)) - { - response.AppendTrailer(headerName, new Microsoft.Extensions.Primitives.StringValues(value.ToArray())); - } - } - } -#endif - } - - private static void AppendResponseHeader(HttpResponse response, string headerName, string[] values) - { - response.Headers.Append(headerName, values); - } + } + + private static void SetResponseTrailingHeaders(IResponseMessage responseMessage, HttpResponse response) + { + if (responseMessage.TrailingHeaders == null) + { + return; + } + +#if TRAILINGHEADERS + foreach (var (headerName, value) in responseMessage.TrailingHeaders) + { + if (ResponseHeadersToFix.TryGetValue(headerName, out var action)) + { + action.Invoke(response, false, value); + } + else + { + // Check if this trailing header can be added to the response + if (response.SupportsTrailers() && !HttpKnownHeaderNames.IsRestrictedResponseHeader(headerName)) + { + response.AppendTrailer(headerName, new Microsoft.Extensions.Primitives.StringValues(value.ToArray())); + } + } + } +#endif + } + + private static void AppendResponseHeader(HttpResponse response, string headerName, string[] values) + { + response.Headers.Append(headerName, values); } } \ No newline at end of file diff --git a/src/WireMock.Net.Minimal/Owin/WireMockMiddlewareOptions.cs b/src/WireMock.Net.Minimal/Owin/WireMockMiddlewareOptions.cs index d94bcd8a..50c97a76 100644 --- a/src/WireMock.Net.Minimal/Owin/WireMockMiddlewareOptions.cs +++ b/src/WireMock.Net.Minimal/Owin/WireMockMiddlewareOptions.cs @@ -2,6 +2,8 @@ using System.Collections.Concurrent; using System.Security.Cryptography.X509Certificates; +using JsonConverter.Abstractions; +using JsonConverter.Newtonsoft.Json; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using WireMock.Handlers; @@ -108,5 +110,9 @@ internal class WireMockMiddlewareOptions : IWireMockMiddlewareOptions /// public ConcurrentDictionary WebSocketRegistries { get; } = new(); + /// public WebSocketSettings? WebSocketSettings { get; set; } + + /// + public IJsonConverter DefaultJsonSerializer { get; set; } = new NewtonsoftJsonConverter(); } \ No newline at end of file diff --git a/src/WireMock.Net.Minimal/Server/WireMockServer.cs b/src/WireMock.Net.Minimal/Server/WireMockServer.cs index 40129a4d..da2dd624 100644 --- a/src/WireMock.Net.Minimal/Server/WireMockServer.cs +++ b/src/WireMock.Net.Minimal/Server/WireMockServer.cs @@ -414,6 +414,7 @@ public partial class WireMockServer : IWireMockServer _options.CorsPolicyOptions = _settings.CorsPolicyOptions; _options.ClientCertificateMode = (Microsoft.AspNetCore.Server.Kestrel.Https.ClientCertificateMode)_settings.ClientCertificateMode; _options.AcceptAnyClientCertificate = _settings.AcceptAnyClientCertificate; + _options.DefaultJsonSerializer = _settings.DefaultJsonSerializer; _httpServer = new AspNetCoreSelfHost(_options, urlOptions); var startTask = _httpServer.StartAsync(); diff --git a/test/WireMock.Net.Tests/Owin/Mappers/OwinResponseMapperTests.cs b/test/WireMock.Net.Tests/Owin/Mappers/OwinResponseMapperTests.cs index 22940adb..e82df9d7 100644 --- a/test/WireMock.Net.Tests/Owin/Mappers/OwinResponseMapperTests.cs +++ b/test/WireMock.Net.Tests/Owin/Mappers/OwinResponseMapperTests.cs @@ -9,6 +9,8 @@ using WireMock.Util; using WireMock.Owin; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Primitives; +using JsonConverter.Newtonsoft.Json; +using JsonConverter.System.Text.Json; namespace WireMock.Net.Tests.Owin.Mappers; @@ -34,6 +36,7 @@ public class OwinResponseMapperTests _optionsMock = new Mock(); _optionsMock.SetupAllProperties(); _optionsMock.SetupGet(o => o.FileSystemHandler).Returns(_fileSystemHandlerMock.Object); + _optionsMock.SetupGet(o => o.DefaultJsonSerializer).Returns(new NewtonsoftJsonConverter()); _headers = new Mock(); _headers.SetupAllProperties(); @@ -186,7 +189,7 @@ public class OwinResponseMapperTests } [Fact] - public async Task OwinResponseMapper_MapAsync_BodyAsJson() + public async Task OwinResponseMapper_MapAsync_BodyAsJson_UsingNewtonsoftJson() { // Arrange var json = new { t = "x", i = (string?)null }; @@ -203,6 +206,25 @@ public class OwinResponseMapperTests _stream.Verify(s => s.WriteAsync(new byte[] { 123, 34, 116, 34, 58, 34, 120, 34, 125 }, 0, 9, It.IsAny()), Times.Once); } + [Fact] + public async Task OwinResponseMapper_MapAsync_BodyAsJson_UsingSystemTextJson() + { + // Arrange + var json = new { t = "x", i = (string?)null }; + var responseMessage = new ResponseMessage + { + Headers = new Dictionary>(), + BodyData = new BodyData { DetectedBodyType = BodyType.Json, BodyAsJson = json, BodyAsJsonIndented = false } + }; + _optionsMock.SetupGet(o => o.DefaultJsonSerializer).Returns(new SystemTextJsonConverter()); + + // Act + await _sut.MapAsync(responseMessage, _responseMock.Object); + + // Assert + _stream.Verify(s => s.WriteAsync(new byte[] { 123, 34, 116, 34, 58, 34, 120, 34, 125 }, 0, 9, It.IsAny()), Times.Once); + } + [Fact] public async Task OwinResponseMapper_MapAsync_SetResponseHeaders() { diff --git a/test/WireMock.Net.Tests/WireMockServerTests.WithBody.cs b/test/WireMock.Net.Tests/WireMockServerTests.WithBody.cs index b6043d00..58261333 100644 --- a/test/WireMock.Net.Tests/WireMockServerTests.WithBody.cs +++ b/test/WireMock.Net.Tests/WireMockServerTests.WithBody.cs @@ -4,10 +4,13 @@ using System.Net; using System.Net.Http; using System.Net.Http.Json; using System.Text; +using System.Text.Json.Serialization; +using JsonConverter.System.Text.Json; using WireMock.Matchers; using WireMock.RequestBuilders; using WireMock.ResponseBuilders; using WireMock.Server; +using WireMock.Settings; namespace WireMock.Net.Tests; @@ -18,11 +21,41 @@ public partial class WireMockServerTests public string? Hi { get; set; } } + public class Person + { + [JsonPropertyName("first_name")] + public string FirstName { get; set; } = string.Empty; + + [JsonPropertyName("last_name")] + public string LastName { get; set; } = string.Empty; + } + + [Fact] + public async Task WireMockServer_WithBodyAsJson_UsingWireMockServerSettings_SystemTextJsonConverter_ShouldReturnCorrectResponse() + { + // Arange + var person = new Person { FirstName = "John", LastName = "Smith" }; + + using var server = WireMockServer.Start(new WireMockServerSettings + { + DefaultJsonSerializer = new SystemTextJsonConverter() + }); + + // Act + server + .Given(Request.Create().UsingAnyMethod()) + .RespondWith(Response.Create().WithBodyAsJson(person)); + + var response = await server.CreateClient().GetStringAsync("/", _ct); + + // Assert + response.Should().BeEquivalentTo("{\"first_name\":\"John\",\"last_name\":\"Smith\"}"); + } + [Fact] public async Task WireMockServer_WithBodyAsJson_Using_PostAsJsonAsync_And_MultipleJmesPathMatchers_ShouldMatch() { // Arrange - var cancellationToken = TestContext.Current.CancellationToken; using var server = WireMockServer.Start(); server.Given( Request.Create() @@ -56,7 +89,7 @@ public partial class WireMockServerTests var requestUri = new Uri($"http://localhost:{server.Port}/a"); var json = new { requestId = "1", value = "A" }; - var response = await server.CreateClient().PostAsJsonAsync(requestUri, json, cancellationToken); + var response = await server.CreateClient().PostAsJsonAsync(requestUri, json, _ct); // Assert response.StatusCode.Should().Be(HttpStatusCode.OK); @@ -68,7 +101,6 @@ public partial class WireMockServerTests public async Task WireMockServer_WithBodyAsJson_Using_PostAsJsonAsync_And_MultipleJmesPathMatchers_ShouldMatch_BestMatching() { // Arrange - var cancellationToken = TestContext.Current.CancellationToken; using var server = WireMockServer.Start(); server.Given( Request.Create() @@ -105,7 +137,7 @@ public partial class WireMockServerTests var requestUri = new Uri($"http://localhost:{server.Port}/a"); var json = new { extra = "X", requestId = "1", value = "A" }; - var response = await server.CreateClient().PostAsJsonAsync(requestUri, json, cancellationToken); + var response = await server.CreateClient().PostAsJsonAsync(requestUri, json, _ct); // Assert response.StatusCode.Should().Be(HttpStatusCode.OK); @@ -117,7 +149,6 @@ public partial class WireMockServerTests public async Task WireMockServer_WithBodyAsJson_Using_PostAsJsonAsync_And_WildcardMatcher_ShouldMatch() { // Arrange - var cancellationToken = TestContext.Current.CancellationToken; using var server = WireMockServer.Start(); server.Given( Request.Create().UsingPost().WithPath("/foo").WithBody(new WildcardMatcher("*Hello*")) @@ -132,7 +163,7 @@ public partial class WireMockServerTests }; // Act - var response = await new HttpClient().PostAsJsonAsync("http://localhost:" + server.Ports[0] + "/foo", jsonObject, cancellationToken); + var response = await new HttpClient().PostAsJsonAsync("http://localhost:" + server.Ports[0] + "/foo", jsonObject, _ct); // Assert response.StatusCode.Should().Be(HttpStatusCode.OK); @@ -144,7 +175,6 @@ public partial class WireMockServerTests public async Task WireMockServer_WithBodyAsJson_Using_PostAsync_And_WildcardMatcher_ShouldMatch() { // Arrange - var cancellationToken = TestContext.Current.CancellationToken; using var server = WireMockServer.Start(); server.Given( Request.Create().UsingPost().WithPath("/foo").WithBody(new WildcardMatcher("*Hello*")) @@ -154,7 +184,7 @@ public partial class WireMockServerTests ); // Act - var response = await new HttpClient().PostAsync("http://localhost:" + server.Ports[0] + "/foo", new StringContent("{ Hi = \"Hello World\" }"), cancellationToken); + var response = await new HttpClient().PostAsync("http://localhost:" + server.Ports[0] + "/foo", new StringContent("{ Hi = \"Hello World\" }"), _ct); // Assert response.StatusCode.Should().Be(HttpStatusCode.OK); @@ -166,7 +196,6 @@ public partial class WireMockServerTests public async Task WireMockServer_WithBodyAsJson_Using_PostAsync_And_JsonPartialWildcardMatcher_ShouldMatch() { // Arrange - var cancellationToken = TestContext.Current.CancellationToken; using var server = WireMockServer.Start(); var matcher = new JsonPartialWildcardMatcher(new { method = "initialize", id = "^[a-f0-9]{32}-[0-9]$" }, ignoreCase: true, regex: true); @@ -188,13 +217,13 @@ public partial class WireMockServerTests // Act var content = "{\"jsonrpc\":\"2.0\",\"id\":\"ec475f56d4694b48bc737500ba575b35-1\",\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{},\"clientInfo\":{\"name\":\"GitHub Test\",\"version\":\"1.0.0\"}}}"; var response = await new HttpClient() - .PostAsync($"{server.Url}/foo", new StringContent(content, Encoding.UTF8, "application/json"), cancellationToken) + .PostAsync($"{server.Url}/foo", new StringContent(content, Encoding.UTF8, "application/json"), _ct) ; // Assert response.StatusCode.Should().Be(HttpStatusCode.OK); - var responseText = await response.Content.ReadAsStringAsync(cancellationToken); + var responseText = await response.Content.ReadAsStringAsync(_ct); responseText.Should().Contain("ec475f56d4694b48bc737500ba575b35-1"); } @@ -203,8 +232,7 @@ public partial class WireMockServerTests public async Task WireMockServer_WithBodyAsJson_Using_PostAsync_And_JsonPartialWildcardMatcher_And_SystemTextJson_ShouldMatch() { // Arrange - var cancellationToken = TestContext.Current.CancellationToken; - using var server = WireMockServer.Start(x => x.DefaultJsonSerializer = new JsonConverter.System.Text.Json.SystemTextJsonConverter() ); + using var server = WireMockServer.Start(x => x.DefaultJsonSerializer = new SystemTextJsonConverter()); var matcher = new JsonPartialWildcardMatcher(new { id = "^[a-f0-9]{32}-[0-9]$" }, ignoreCase: true, regex: true); server.Given(Request.Create() @@ -220,12 +248,12 @@ public partial class WireMockServerTests // Act var content = """{"id":"ec475f56d4694b48bc737500ba575b35-1"}"""; using var httpClient = new HttpClient(); - var response = await httpClient.PostAsync($"{server.Url}/system-text-json", new StringContent(content, Encoding.UTF8, "application/json"), cancellationToken); + var response = await httpClient.PostAsync($"{server.Url}/system-text-json", new StringContent(content, Encoding.UTF8, "application/json"), _ct); // Assert response.StatusCode.Should().Be(HttpStatusCode.OK); - var responseText = await response.Content.ReadAsStringAsync(cancellationToken); + var responseText = await response.Content.ReadAsStringAsync(_ct); responseText.Should().Contain("OK"); } #endif @@ -234,7 +262,6 @@ public partial class WireMockServerTests public async Task WireMockServer_WithBodyAsFormUrlEncoded_Using_PostAsync_And_WithFunc() { // Arrange - var cancelationToken = TestContext.Current.CancellationToken; using var server = WireMockServer.Start(); server.Given( Request.Create() @@ -249,7 +276,7 @@ public partial class WireMockServerTests // Act var content = new FormUrlEncodedContent([new KeyValuePair("key1", "value1")]); var response = await new HttpClient() - .PostAsync($"{server.Url}/foo", content, cancelationToken); + .PostAsync($"{server.Url}/foo", content, _ct); // Assert response.StatusCode.Should().Be(HttpStatusCode.OK); @@ -261,7 +288,6 @@ public partial class WireMockServerTests public async Task WireMockServer_WithBodyAsFormUrlEncoded_Using_PostAsync_And_WithExactMatcher() { // Arrange - var cancellationToken = TestContext.Current.CancellationToken; using var server = WireMockServer.Start(); server.Given( Request.Create() @@ -282,7 +308,7 @@ public partial class WireMockServerTests new KeyValuePair("email", "johndoe@example.com") ]); using var httpClient = new HttpClient(); - var response = await httpClient.PostAsync($"{server.Url}/foo", content, cancellationToken) + var response = await httpClient.PostAsync($"{server.Url}/foo", content, _ct) ; // Assert response.StatusCode.Should().Be(HttpStatusCode.OK); @@ -294,7 +320,6 @@ public partial class WireMockServerTests public async Task WireMockServer_WithBodyAsFormUrlEncoded_Using_PostAsync_And_WithFormUrlEncodedMatcher() { // Arrange - var cancelationToken = TestContext.Current.CancellationToken; var matcher = new FormUrlEncodedMatcher(["email=johndoe@example.com", "name=John Doe"]); using var server = WireMockServer.Start(); server.Given( @@ -326,7 +351,7 @@ public partial class WireMockServerTests new KeyValuePair("email", "johndoe@example.com") ]); var responseOrdered = await new HttpClient() - .PostAsync($"{server.Url}/foo", contentOrdered, cancelationToken) + .PostAsync($"{server.Url}/foo", contentOrdered, _ct) ; // Assert 1 @@ -340,7 +365,7 @@ public partial class WireMockServerTests new KeyValuePair("name", "John Doe"), ]); var responseUnordered = await new HttpClient() - .PostAsync($"{server.Url}/bar", contentUnordered, cancelationToken) + .PostAsync($"{server.Url}/bar", contentUnordered, _ct) ; // Assert 2 @@ -353,7 +378,6 @@ public partial class WireMockServerTests public async Task WireMockServer_WithSseBody() { // Arrange - var cancellationToken = TestContext.Current.CancellationToken; using var server = WireMockServer.Start(); server .WhenRequest(r => r @@ -387,9 +411,8 @@ public partial class WireMockServerTests using var client = new HttpClient(); // Act 1 - var normal = await client.GetAsync(server.Url, cancellationToken) -; - (await normal.Content.ReadAsStringAsync(cancellationToken)).Should().Be("normal"); + var normal = await client.GetAsync(server.Url, _ct); + (await normal.Content.ReadAsStringAsync(_ct)).Should().Be("normal"); // Act 2 using var response = await client.GetStreamAsync($"{server.Url}/sse", _ct);