diff --git a/src/WireMock.Net/Serialization/PactMapper.cs b/src/WireMock.Net/Serialization/PactMapper.cs index d288dd3e..8062a7da 100644 --- a/src/WireMock.Net/Serialization/PactMapper.cs +++ b/src/WireMock.Net/Serialization/PactMapper.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; -using DevLab.JmesPath.Interop; using WireMock.Admin.Mappings; using WireMock.Extensions; -using WireMock.Matchers; using WireMock.Pact.Models.V2; using WireMock.Server; using WireMock.Util; @@ -88,9 +86,9 @@ internal static class PactMapper return response.BodyAsJson; } - if (response?.Body != null) // In case the body is a string, try to deserialize into object, else just return the string + if (response?.Body != null) { - return JsonUtils.TryDeserializeObject(response.Body) ?? response.Body; + return TryDeserializeJsonStringAsObject(response.Body); } return null; @@ -140,18 +138,26 @@ internal static class PactMapper private static object? MapBody(BodyModel? body) { - if (body?.Matcher == null || body.Matchers == null) + return MapMatcherPattern(body?.Matcher ?? body?.Matchers?.FirstOrDefault()); + } + + private static object? MapMatcherPattern(MatcherModel? matcher) + { + var pattern = matcher?.Pattern ?? matcher?.Patterns?.FirstOrDefault(); + if (pattern is string patternAsString) { - return null; + return TryDeserializeJsonStringAsObject(patternAsString); } - if (body.Matcher is { Name: nameof(JsonMatcher) }) - { - return body.Matcher.Pattern; - } + return pattern; + } - var jsonMatcher = body.Matchers.FirstOrDefault(m => m.Name == nameof(JsonMatcher)); - return jsonMatcher?.Pattern; + /// + /// In case it's a string, try to deserialize into object, else just return the string + /// + private static object? TryDeserializeJsonStringAsObject(string? value) + { + return value != null ? JsonUtils.TryDeserializeObject(value) ?? value : null; } //private static string GetPatternAsStringFromMatchers(MatcherModel[]? matchers, string defaultValue) diff --git a/test/WireMock.Net.Tests/Pact/PactTests.cs b/test/WireMock.Net.Tests/Pact/PactTests.cs index ba411a13..e02e2572 100644 --- a/test/WireMock.Net.Tests/Pact/PactTests.cs +++ b/test/WireMock.Net.Tests/Pact/PactTests.cs @@ -101,6 +101,58 @@ public class PactTests pact.Interactions[0].Response.Body.Should().Be("test"); } + [Fact] + public void SavePact_Get_Request_And_Response_WithNullBody() + { + // Act + var server = WireMockServer.Start(); + server + .Given(Request.Create() + .UsingGet() + .WithPath("/tester") + ) + .RespondWith( + Response.Create() + .WithStatusCode(HttpStatusCode.OK) + ); + + var memoryStream = new MemoryStream(); + server.SavePact(memoryStream); + + var json = Encoding.UTF8.GetString(memoryStream.ToArray()); + var pact = JsonConvert.DeserializeObject(json)!; + + // Assert + pact.Interactions.Should().HaveCount(1); + pact.Interactions[0].Response.Body.Should().BeNull(); + } + + [Fact] + public void SavePact_Post_Request_WithBody_JsonPartialMatcher() + { + // Act + var server = WireMockServer.Start(); + server + .Given(Request.Create() + .UsingPost() + .WithBody(new JsonPartialMatcher(@"{ ""name"": ""stef"" }")) + .WithPath("/tester") + ) + .RespondWith(Response.Create()); + + var memoryStream = new MemoryStream(); + server.SavePact(memoryStream); + + var json = Encoding.UTF8.GetString(memoryStream.ToArray()); + var pact = JsonConvert.DeserializeObject(json)!; + + // Assert + pact.Interactions.Should().HaveCount(1); + + var expectedBody = new JObject { { "name", "stef" } }; + pact.Interactions[0].Request.Body.Should().BeEquivalentTo(expectedBody); + } + [Fact] public void SavePact_Multiple_Requests() { diff --git a/test/WireMock.Net.Tests/Pact/files/pact-multiple.json b/test/WireMock.Net.Tests/Pact/files/pact-multiple.json index e2231f5d..5dc41267 100644 --- a/test/WireMock.Net.Tests/Pact/files/pact-multiple.json +++ b/test/WireMock.Net.Tests/Pact/files/pact-multiple.json @@ -32,7 +32,11 @@ "Accept": "application/json" }, "method": "POST", - "path": "/add" + "path": "/add", + "body": { + "Id": "1", + "FirstName": "Totally" + } }, "response": { "body": {