Skip to content

Commit e20a90b

Browse files
authored
Fix MappingConverter to support Body with JsonMatcher (#1101)
* Fix MappingBuilder for Body * . * . * Fix MappingConverter
1 parent 9210957 commit e20a90b

11 files changed

+300
-70
lines changed

src/WireMock.Net/Serialization/MappingConverter.cs

+11-15
Original file line numberDiff line numberDiff line change
@@ -143,25 +143,21 @@ public string ToCSharpCode(IMapping mapping, MappingConverterSettings? settings
143143

144144
if (requestMessageBodyMatcher is { Matchers: { } })
145145
{
146-
if (requestMessageBodyMatcher.Matchers.OfType<WildcardMatcher>().FirstOrDefault() is { } wildcardMatcher && wildcardMatcher.GetPatterns().Any())
146+
var firstMatcher = requestMessageBodyMatcher.Matchers.FirstOrDefault();
147+
148+
if (firstMatcher is WildcardMatcher wildcardMatcher && wildcardMatcher.GetPatterns().Any())
147149
{
148150
sb.AppendLine($" .WithBody({GetString(wildcardMatcher)})");
149151
}
150-
else if (requestMessageBodyMatcher.Matchers.OfType<JsonPartialMatcher>().FirstOrDefault() is { Value: { } } jsonPartialMatcher)
151-
{
152-
sb.AppendLine(@$" .WithBody(new JsonPartialMatcher(
153-
value: {ToCSharpStringLiteral(jsonPartialMatcher.Value.ToString())},
154-
ignoreCase: {ToCSharpBooleanLiteral(jsonPartialMatcher.IgnoreCase)},
155-
regex: {ToCSharpBooleanLiteral(jsonPartialMatcher.Regex)}
156-
))");
157-
}
158-
else if (requestMessageBodyMatcher.Matchers.OfType<JsonPartialWildcardMatcher>().FirstOrDefault() is { Value: { } } jsonPartialWildcardMatcher)
152+
153+
if (firstMatcher is JsonMatcher jsonMatcher)
159154
{
160-
sb.AppendLine(@$" .WithBody(new JsonPartialWildcardMatcher(
161-
value: {ToCSharpStringLiteral(jsonPartialWildcardMatcher.Value.ToString())},
162-
ignoreCase: {ToCSharpBooleanLiteral(jsonPartialWildcardMatcher.IgnoreCase)},
163-
regex: {ToCSharpBooleanLiteral(jsonPartialWildcardMatcher.Regex)}
164-
))");
155+
var matcherType = jsonMatcher.GetType().Name;
156+
sb.AppendLine($" .WithBody(new {matcherType}(");
157+
sb.AppendLine($" value: {ConvertToAnonymousObjectDefinition(jsonMatcher.Value, 3)},");
158+
sb.AppendLine($" ignoreCase: {ToCSharpBooleanLiteral(jsonMatcher.IgnoreCase)},");
159+
sb.AppendLine($" regex: {ToCSharpBooleanLiteral(jsonMatcher.Regex)}");
160+
sb.AppendLine(@" ))");
165161
}
166162
}
167163

src/WireMock.Net/Server/WireMockServer.Admin.cs

+2-4
Original file line numberDiff line numberDiff line change
@@ -344,15 +344,13 @@ private IResponseMessage MappingCodeGet(IRequestMessage requestMessage)
344344

345345
private static MappingConverterType GetMappingConverterType(IRequestMessage requestMessage)
346346
{
347-
var mappingConverterType = MappingConverterType.Server;
348-
349347
if (requestMessage.QueryIgnoreCase?.TryGetValue(nameof(MappingConverterType), out var values) == true &&
350348
Enum.TryParse(values.FirstOrDefault(), true, out MappingConverterType parsed))
351349
{
352-
mappingConverterType = parsed;
350+
return parsed;
353351
}
354352

355-
return mappingConverterType;
353+
return MappingConverterType.Server;
356354
}
357355

358356
private IMapping? FindMappingByGuid(IRequestMessage requestMessage)

src/WireMock.Net/Util/CSharpFormatter.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ namespace WireMock.Util;
1010

1111
internal static class CSharpFormatter
1212
{
13+
private const string Null = "null";
14+
1315
#region Reserved Keywords
1416
private static readonly HashSet<string> CSharpReservedKeywords = new(new[]
1517
{
@@ -92,17 +94,15 @@ internal static class CSharpFormatter
9294
"while"
9395
});
9496
#endregion
95-
96-
private const string Null = "null";
97-
98-
public static object ConvertToAnonymousObjectDefinition(object jsonBody)
97+
98+
public static object ConvertToAnonymousObjectDefinition(object jsonBody, int ind = 2)
9999
{
100100
var serializedBody = JsonConvert.SerializeObject(jsonBody);
101101
using var jsonReader = new JsonTextReader(new StringReader(serializedBody));
102102
jsonReader.DateParseHandling = DateParseHandling.None;
103103
var deserializedBody = JObject.Load(jsonReader);
104104

105-
return ConvertJsonToAnonymousObjectDefinition(deserializedBody, 2);
105+
return ConvertJsonToAnonymousObjectDefinition(deserializedBody, ind);
106106
}
107107

108108
public static string ConvertJsonToAnonymousObjectDefinition(JToken token, int ind = 0)

test/WireMock.Net.Tests/AdminApi/WireMockAdminApiTests.IWireMockAdminApi_GetMappingsCode.verified.txt

+41-20
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,49 @@
11
var server = WireMockServer.Start();
2+
server
3+
.Given(Request.Create()
4+
.UsingMethod("POST")
5+
.WithPath("/users/post1")
6+
.WithBody(new JsonMatcher(
7+
value: new
8+
{
9+
city = "Amsterdam",
10+
country = "The Netherlands"
11+
},
12+
ignoreCase: false,
13+
regex: false
14+
))
15+
)
16+
.WithGuid("90356dba-b36c-469a-a17e-669cd84f1f05")
17+
.RespondWith(Response.Create()
18+
);
19+
20+
server
21+
.Given(Request.Create()
22+
.UsingMethod("POST")
23+
.WithPath("/users/post2")
24+
.WithBody(new JsonPartialMatcher(
25+
value: new
26+
{
27+
city = "City",
28+
country = "Country"
29+
},
30+
ignoreCase: false,
31+
regex: false
32+
))
33+
)
34+
.WithGuid("1b731398-4a5b-457f-a6e3-d65e541c428f")
35+
.RespondWith(Response.Create()
36+
.WithBody(@"Line1
37+
Some ""value"" in Line2")
38+
);
39+
240
server
341
.Given(Request.Create()
442
.UsingMethod("GET")
543
.WithPath("/foo1")
644
.WithParam("p1", "xyz")
745
)
8-
.WithGuid("90356dba-b36c-469a-a17e-669cd84f1f05")
46+
.WithGuid("f74fd144-df53-404f-8e35-da22a640bd5f")
947
.RespondWith(Response.Create()
1048
.WithStatusCode(200)
1149
.WithBody("1")
@@ -18,7 +56,7 @@ server
1856
.WithParam("p2", "abc")
1957
.WithHeader("h1", "W/\"234f2q3r\"", true)
2058
)
21-
.WithGuid("1b731398-4a5b-457f-a6e3-d65e541c428f")
59+
.WithGuid("4126dec8-470b-4eff-93bb-c24f83b8b1fd")
2260
.RespondWith(Response.Create()
2361
.WithStatusCode("201")
2462
.WithHeader("hk", "hv")
@@ -31,7 +69,7 @@ server
3169
.UsingMethod("DELETE")
3270
.WithUrl("https://localhost/test")
3371
)
34-
.WithGuid("f74fd144-df53-404f-8e35-da22a640bd5f")
72+
.WithGuid("c9929240-7ae8-4a5d-8ed8-0913479f6eeb")
3573
.RespondWith(Response.Create()
3674
.WithStatusCode(208)
3775
.WithBodyAsJson(new
@@ -70,20 +108,3 @@ text
70108
})
71109
);
72110

73-
server
74-
.Given(Request.Create()
75-
.UsingMethod("POST")
76-
.WithPath("/foo3")
77-
.WithBody(new JsonPartialMatcher(
78-
value: "{ a = 1, b = 2 }",
79-
ignoreCase: false,
80-
regex: false
81-
))
82-
)
83-
.WithGuid("4126dec8-470b-4eff-93bb-c24f83b8b1fd")
84-
.RespondWith(Response.Create()
85-
.WithStatusCode(200)
86-
.WithBody(@"Line1
87-
Some ""value"" in Line2")
88-
);
89-

test/WireMock.Net.Tests/AdminApi/WireMockAdminApiTests.cs

+57-21
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ public async Task IWireMockAdminApi_GetMappingAsync_WithProxy_And_ProxyUrlReplac
491491

492492
server.Stop();
493493
}
494-
494+
495495
[Fact]
496496
public async Task IWireMockAdminApi_GetRequestsAsync_Json()
497497
{
@@ -862,16 +862,45 @@ public async Task IWireMockAdminApi_GetMappingsCode()
862862
var guid2 = Guid.Parse("1b731398-4a5b-457f-a6e3-d65e541c428f");
863863
var guid3 = Guid.Parse("f74fd144-df53-404f-8e35-da22a640bd5f");
864864
var guid4 = Guid.Parse("4126DEC8-470B-4EFF-93BB-C24F83B8B1FD");
865+
var guid5 = Guid.Parse("c9929240-7ae8-4a5d-8ed8-0913479f6eeb");
865866
var server = WireMockServer.StartWithAdminInterface();
866867

868+
server
869+
.Given(
870+
Request.Create()
871+
.WithPath("/users/post1")
872+
.UsingPost()
873+
.WithBody(new JsonMatcher(new
874+
{
875+
city = "Amsterdam",
876+
country = "The Netherlands"
877+
}))
878+
)
879+
.WithGuid(guid1)
880+
.RespondWith(Response.Create());
881+
882+
server
883+
.Given(
884+
Request.Create()
885+
.WithPath("/users/post2")
886+
.UsingPost()
887+
.WithBody(new JsonPartialMatcher(new
888+
{
889+
city = "City",
890+
country = "Country"
891+
}))
892+
)
893+
.WithGuid(guid2)
894+
.RespondWith(Response.Create().WithBody("Line1\r\nSome \"value\" in Line2"));
895+
867896
server
868897
.Given(
869898
Request.Create()
870899
.WithPath("/foo1")
871900
.WithParam("p1", "xyz")
872901
.UsingGet()
873902
)
874-
.WithGuid(guid1)
903+
.WithGuid(guid3)
875904
.RespondWith(
876905
Response.Create()
877906
.WithStatusCode(200)
@@ -886,7 +915,7 @@ public async Task IWireMockAdminApi_GetMappingsCode()
886915
.WithHeader("h1", "W/\"234f2q3r\"")
887916
.UsingPost()
888917
)
889-
.WithGuid(guid2)
918+
.WithGuid(guid4)
890919
.RespondWith(
891920
Response.Create()
892921
.WithStatusCode("201")
@@ -901,36 +930,43 @@ public async Task IWireMockAdminApi_GetMappingsCode()
901930
.WithUrl("https://localhost/test")
902931
.UsingDelete()
903932
)
904-
.WithGuid(guid3)
933+
.WithGuid(guid5)
905934
.RespondWith(
906935
Response.Create()
907936
.WithStatusCode(HttpStatusCode.AlreadyReported)
908-
.WithBodyAsJson(new { @as = 1, b = 1.2, d = true, e = false, f = new[] { 1, 2, 3, 4 }, g = new { z1 = 1, z2 = 2, z3 = new[] { "a", "b", "c" }, z4 = new[] { new { a = 1, b = 2 }, new { a = 2, b = 3 } } }, date_field = new DateTime(2023, 05, 08, 11, 20, 19), string_field_with_date = "2021-03-13T21:04:00Z", multiline_text = @"This
937+
.WithBodyAsJson(new
938+
{
939+
@as = 1,
940+
b = 1.2,
941+
d = true,
942+
e = false,
943+
f = new[] { 1, 2, 3, 4 },
944+
g = new
945+
{
946+
z1 = 1,
947+
z2 = 2,
948+
z3 = new[] { "a", "b", "c" },
949+
z4 = new[]
950+
{
951+
new { a = 1, b = 2 },
952+
new { a = 2, b = 3 }
953+
}
954+
},
955+
date_field = new DateTime(2023, 05, 08, 11, 20, 19),
956+
string_field_with_date = "2021-03-13T21:04:00Z",
957+
multiline_text = @"This
909958
is
910959
multiline
911960
text
912-
" })
913-
);
914-
915-
server
916-
.Given(
917-
Request.Create()
918-
.WithPath("/foo3")
919-
.WithBody(new JsonPartialMatcher(new { a = 1, b = 2 }))
920-
.UsingPost()
921-
)
922-
.WithGuid(guid4)
923-
.RespondWith(
924-
Response.Create()
925-
.WithStatusCode(200)
926-
.WithBody("Line1\r\nSome \"value\" in Line2")
961+
"
962+
})
927963
);
928964

929965
// Act
930966
var api = RestClient.For<IWireMockAdminApi>(server.Url);
931967

932968
var mappings = await api.GetMappingsAsync().ConfigureAwait(false);
933-
mappings.Should().HaveCount(4);
969+
mappings.Should().HaveCount(5);
934970

935971
var code = await api.GetMappingsCodeAsync().ConfigureAwait(false);
936972

test/WireMock.Net.Tests/MappingBuilderTests.GetMappings.verified.txt

+30
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,35 @@
3131
BodyDestination: SameAsSource,
3232
Body: { msg: "Hello world!"}
3333
}
34+
},
35+
{
36+
Guid: Guid_2,
37+
UpdatedAt: 2023-01-14 15:16:17,
38+
Request: {
39+
Path: {
40+
Matchers: [
41+
{
42+
Name: WildcardMatcher,
43+
Pattern: /users/post2,
44+
IgnoreCase: false
45+
}
46+
]
47+
},
48+
Methods: [
49+
POST
50+
],
51+
Body: {
52+
Matcher: {
53+
Name: JsonMatcher,
54+
Pattern: {
55+
city: Amsterdam,
56+
country: The Netherlands
57+
},
58+
IgnoreCase: false,
59+
Regex: false
60+
}
61+
}
62+
},
63+
Response: {}
3464
}
3565
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
var builder = new MappingBuilder();
2+
builder
3+
.Given(Request.Create()
4+
.UsingMethod("GET")
5+
.WithPath("/foo")
6+
.WithParam("test", "it.Length < 10")
7+
)
8+
.WithGuid("41372914-1838-4c67-916b-b9aacdd096ce")
9+
.RespondWith(Response.Create()
10+
.WithBody("{ msg: \"Hello world!\"}")
11+
);
12+
13+
builder
14+
.Given(Request.Create()
15+
.UsingMethod("POST")
16+
.WithPath("/users/post2")
17+
.WithBody(new JsonMatcher(
18+
value: new
19+
{
20+
city = "Amsterdam",
21+
country = "The Netherlands"
22+
},
23+
ignoreCase: false,
24+
regex: false
25+
))
26+
)
27+
.WithGuid("98fae52e-76df-47d9-876f-2ee32e931d9b")
28+
.RespondWith(Response.Create()
29+
);
30+

0 commit comments

Comments
 (0)