mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-06-11 16:22:54 +02:00
Fix ExactMatcher and JsonMatcher not working for ISO dates as string (#1443)
This commit is contained in:
@@ -25,7 +25,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="JsonConverter.Abstractions" Version="0.8.0" />
|
<PackageReference Include="JsonConverter.Abstractions" Version="0.9.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
using JsonConverter.Abstractions;
|
using JsonConverter.Abstractions;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
#if NETSTANDARD2_0_OR_GREATER || NETCOREAPP3_1_OR_GREATER || NET6_0_OR_GREATER || NET461
|
#if NETSTANDARD2_0_OR_GREATER || NETCOREAPP3_1_OR_GREATER || NET6_0_OR_GREATER || NET461
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
@@ -10,9 +11,15 @@ namespace WireMock.Serialization;
|
|||||||
|
|
||||||
internal class MappingSerializer(IJsonConverter jsonConverter)
|
internal class MappingSerializer(IJsonConverter jsonConverter)
|
||||||
{
|
{
|
||||||
|
private static readonly JsonConverterOptions JsonConverterOptions = new JsonConverterOptions
|
||||||
|
{
|
||||||
|
DateParseHandling = (int) DateParseHandling.None
|
||||||
|
};
|
||||||
|
|
||||||
internal T[] DeserializeJsonToArray<T>(string value)
|
internal T[] DeserializeJsonToArray<T>(string value)
|
||||||
{
|
{
|
||||||
return DeserializeObjectToArray<T>(jsonConverter.Deserialize<object>(value)!);
|
// DeserializeObject
|
||||||
|
return DeserializeObjectToArray<T>(jsonConverter.Deserialize<object>(value, JsonConverterOptions)!);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static T[] DeserializeObjectToArray<T>(object value)
|
internal static T[] DeserializeObjectToArray<T>(object value)
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
@@ -26,9 +25,6 @@ using WireMock.Util;
|
|||||||
|
|
||||||
namespace WireMock.Server;
|
namespace WireMock.Server;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The fluent mock server.
|
|
||||||
/// </summary>
|
|
||||||
public partial class WireMockServer
|
public partial class WireMockServer
|
||||||
{
|
{
|
||||||
private const int EnhancedFileSystemWatcherTimeoutMs = 1000;
|
private const int EnhancedFileSystemWatcherTimeoutMs = 1000;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.8.0" />
|
<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.9.0" />
|
||||||
<PackageReference Include="NUnit" Version="4.4.0" />
|
<PackageReference Include="NUnit" Version="4.4.0" />
|
||||||
<PackageReference Include="Stef.Validation" Version="0.2.0" />
|
<PackageReference Include="Stef.Validation" Version="0.2.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.8.0" />
|
<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.9.0" />
|
||||||
<PackageReference Include="RestEase" Version="1.6.4" />
|
<PackageReference Include="RestEase" Version="1.6.4" />
|
||||||
<PackageReference Include="Stef.Validation" Version="0.2.0" />
|
<PackageReference Include="Stef.Validation" Version="0.2.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
<PackageReference Include="Stef.Validation" Version="0.2.0" />
|
<PackageReference Include="Stef.Validation" Version="0.2.0" />
|
||||||
<PackageReference Include="AnyOf" Version="0.5.0.1" />
|
<PackageReference Include="AnyOf" Version="0.5.0.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
|
||||||
<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.8.0" />
|
<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.9.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
using JsonConverter.Newtonsoft.Json;
|
using JsonConverter.Newtonsoft.Json;
|
||||||
using WireMock.Admin.Mappings;
|
using WireMock.Admin.Mappings;
|
||||||
using WireMock.Serialization;
|
using WireMock.Serialization;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
#if NET8_0_OR_GREATER
|
#if NET8_0_OR_GREATER
|
||||||
using JsonConverter.System.Text.Json;
|
using JsonConverter.System.Text.Json;
|
||||||
#endif
|
#endif
|
||||||
@@ -319,5 +321,92 @@ public class MappingSerializerTests
|
|||||||
act.Should().Throw<InvalidOperationException>()
|
act.Should().Throw<InvalidOperationException>()
|
||||||
.WithMessage("Cannot deserialize the provided value to an array or object.");
|
.WithMessage("Cannot deserialize the provided value to an array or object.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MappingSerializer_DeserializeJsonToArray_WithNewtonsoftJson_DateTimeStringInQueryParamExactMatcherPattern_ShouldPreservePatternAsString()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var jsonConverter = new NewtonsoftJsonConverter();
|
||||||
|
var serializer = new MappingSerializer(jsonConverter);
|
||||||
|
var mappingJson =
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
"Guid": "12345678-1234-1234-1234-aaaaaaaaaaaa",
|
||||||
|
"Request": {
|
||||||
|
"Path": "/api/report",
|
||||||
|
"Methods": ["GET"],
|
||||||
|
"Params": [
|
||||||
|
{
|
||||||
|
"Name": "asOfDate",
|
||||||
|
"Matchers": [
|
||||||
|
{
|
||||||
|
"Name": "ExactMatcher",
|
||||||
|
"Pattern": "2021-11-10T13:39:13.705"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Response": {
|
||||||
|
"StatusCode": 200
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = serializer.DeserializeJsonToArray<MappingModel>(mappingJson);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Should().HaveCount(1);
|
||||||
|
var matcher = result[0].Request!.Params![0].Matchers![0];
|
||||||
|
matcher.Name.Should().Be("ExactMatcher");
|
||||||
|
matcher.Pattern.Should().BeOfType<string>()
|
||||||
|
.Which.Should().Be("2021-11-10T13:39:13.705",
|
||||||
|
"datetime-format strings in ExactMatcher Pattern fields must survive deserialization as strings, " +
|
||||||
|
"not be auto-converted to DateTime by Newtonsoft.Json's DateParseHandling.DateTime");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MappingSerializer_DeserializeJsonToArray_WithNewtonsoftJson_DateTimeStringInJsonMatcherBodyPattern_ShouldPreservePatternAsString()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var jsonConverter = new NewtonsoftJsonConverter();
|
||||||
|
var serializer = new MappingSerializer(jsonConverter);
|
||||||
|
// Pattern is an INLINE JSON object (not a string) - this is how WireMock mapping files store
|
||||||
|
// JsonMatcher patterns when recorded. Newtonsoft with DateParseHandling.DateTime will convert
|
||||||
|
// the datetime value inside the JObject to JTokenType.Date during deserialization.
|
||||||
|
var mappingJson =
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
"Guid": "12345678-1234-1234-1234-bbbbbbbbbbbb",
|
||||||
|
"Request": {
|
||||||
|
"Path": "/api/report",
|
||||||
|
"Methods": ["POST"],
|
||||||
|
"Body": {
|
||||||
|
"Matcher": {
|
||||||
|
"Name": "JsonMatcher",
|
||||||
|
"Pattern": {"Date": "2021-09-30T00:00:00Z", "Names": ["Cash"]}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Response": {
|
||||||
|
"StatusCode": 200
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = serializer.DeserializeJsonToArray<MappingModel>(mappingJson);
|
||||||
|
|
||||||
|
// Assert - datetime values inside the JObject pattern must remain JTokenType.String.
|
||||||
|
result.Should().HaveCount(1);
|
||||||
|
var matcher = result[0].Request!.Body!.Matcher!;
|
||||||
|
matcher.Name.Should().Be("JsonMatcher");
|
||||||
|
var patternJObject = matcher.Pattern.Should().BeOfType<JObject>().Subject;
|
||||||
|
patternJObject["Date"]!.Type.Should().Be(JTokenType.String,
|
||||||
|
"datetime-format strings inside an inline JsonMatcher body pattern must retain JTokenType.String " +
|
||||||
|
"after deserialization; if DateParseHandling.DateTime auto-converts them to JTokenType.Date, " +
|
||||||
|
"JToken.DeepEquals will fail against incoming request bodies parsed with DateParseHandling.None");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user