From 25666152bb50d975dd84cf2288afd5e430918a5c Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Wed, 27 Oct 2021 08:16:18 +0200 Subject: [PATCH] Add JsonPartialWildcardMatcher (#667) * JsonPartialWildcardMatcher * . * more tests --- .../Matchers/AbstractJsonPartialMatcher.cs | 89 ++++ .../Matchers/JsonPartialMatcher.cs | 73 +--- .../Matchers/JsonPartialWildCardMatcher.cs | 38 ++ .../Serialization/MatcherMapper.cs | 30 +- .../JsonPartialWildcardMatcherTests.cs | 400 ++++++++++++++++++ .../Serialization/MatcherMapperTests.cs | 19 + 6 files changed, 575 insertions(+), 74 deletions(-) create mode 100644 src/WireMock.Net/Matchers/AbstractJsonPartialMatcher.cs create mode 100644 src/WireMock.Net/Matchers/JsonPartialWildCardMatcher.cs create mode 100644 test/WireMock.Net.Tests/Matchers/JsonPartialWildcardMatcherTests.cs diff --git a/src/WireMock.Net/Matchers/AbstractJsonPartialMatcher.cs b/src/WireMock.Net/Matchers/AbstractJsonPartialMatcher.cs new file mode 100644 index 00000000..70d610f1 --- /dev/null +++ b/src/WireMock.Net/Matchers/AbstractJsonPartialMatcher.cs @@ -0,0 +1,89 @@ +using System.Collections.Generic; +using System.Linq; +using JetBrains.Annotations; +using Newtonsoft.Json.Linq; + +namespace WireMock.Matchers +{ + /// + /// Generic AbstractJsonPartialMatcher + /// + public abstract class AbstractJsonPartialMatcher : JsonMatcher + { + /// + /// Initializes a new instance of the class. + /// + /// The string value to check for equality. + /// Ignore the case from the PropertyName and PropertyValue (string only). + /// Throw an exception when the internal matching fails because of invalid input. + protected AbstractJsonPartialMatcher([NotNull] string value, bool ignoreCase = false, bool throwException = false) + : base(value, ignoreCase, throwException) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The object value to check for equality. + /// Ignore the case from the PropertyName and PropertyValue (string only). + /// Throw an exception when the internal matching fails because of invalid input. + protected AbstractJsonPartialMatcher([NotNull] object value, bool ignoreCase = false, bool throwException = false) + : base(value, ignoreCase, throwException) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The value to check for equality. + /// Ignore the case from the PropertyName and PropertyValue (string only). + /// Throw an exception when the internal matching fails because of invalid input. + protected AbstractJsonPartialMatcher(MatchBehaviour matchBehaviour, [NotNull] object value, bool ignoreCase = false, bool throwException = false) + : base(matchBehaviour, value, ignoreCase, throwException) + { + } + + /// + protected override bool IsMatch(JToken value, JToken input) + { + if (value == null || value == input) + { + return true; + } + + if (input == null || value.Type != input.Type) + { + return false; + } + + switch (value.Type) + { + case JTokenType.Object: + var nestedValues = value.ToObject>(); + return nestedValues?.Any() != true || + nestedValues.All(pair => IsMatch(pair.Value, input.SelectToken(pair.Key))); + + case JTokenType.Array: + var valuesArray = value.ToObject(); + var tokenArray = input.ToObject(); + + if (valuesArray?.Any() != true) + { + return true; + } + + return tokenArray?.Any() == true && + valuesArray.All(subFilter => tokenArray.Any(subToken => IsMatch(subFilter, subToken))); + + default: + return IsMatch(value.ToString(), input.ToString()); + } + } + + /// + /// Check if two strings are a match (matching can be done exact or wildcard) + /// + protected abstract bool IsMatch(string value, string input); + } +} diff --git a/src/WireMock.Net/Matchers/JsonPartialMatcher.cs b/src/WireMock.Net/Matchers/JsonPartialMatcher.cs index 54b04cb5..3e457393 100644 --- a/src/WireMock.Net/Matchers/JsonPartialMatcher.cs +++ b/src/WireMock.Net/Matchers/JsonPartialMatcher.cs @@ -1,87 +1,38 @@ -using System.Collections.Generic; -using System.Linq; using JetBrains.Annotations; -using Newtonsoft.Json.Linq; namespace WireMock.Matchers { /// /// JsonPartialMatcher /// - public class JsonPartialMatcher : JsonMatcher + public class JsonPartialMatcher : AbstractJsonPartialMatcher { - /// - public override string Name => "JsonPartialMatcher"; + /// + public override string Name => nameof(JsonPartialMatcher); - /// - /// Initializes a new instance of the class. - /// - /// The string value to check for equality. - /// Ignore the case from the PropertyName and PropertyValue (string only). - /// Throw an exception when the internal matching fails because of invalid input. - public JsonPartialMatcher([NotNull] string value, bool ignoreCase = false, bool throwException = false) + /// + public JsonPartialMatcher([NotNull] string value, bool ignoreCase = false, bool throwException = false) : base(value, ignoreCase, throwException) { } - /// - /// Initializes a new instance of the class. - /// - /// The object value to check for equality. - /// Ignore the case from the PropertyName and PropertyValue (string only). - /// Throw an exception when the internal matching fails because of invalid input. - public JsonPartialMatcher([NotNull] object value, bool ignoreCase = false, bool throwException = false) + /// + public JsonPartialMatcher([NotNull] object value, bool ignoreCase = false, bool throwException = false) : base(value, ignoreCase, throwException) { } - /// - /// Initializes a new instance of the class. - /// - /// The match behaviour. - /// The value to check for equality. - /// Ignore the case from the PropertyName and PropertyValue (string only). - /// Throw an exception when the internal matching fails because of invalid input. - public JsonPartialMatcher(MatchBehaviour matchBehaviour, [NotNull] object value, bool ignoreCase = false, bool throwException = false) + /// + public JsonPartialMatcher(MatchBehaviour matchBehaviour, [NotNull] object value, bool ignoreCase = false, bool throwException = false) : base(matchBehaviour, value, ignoreCase, throwException) { } /// - protected override bool IsMatch(JToken value, JToken input) + protected override bool IsMatch(string value, string input) { - if (value == null || value == input) - { - return true; - } - - if (input == null || value.Type != input.Type) - { - return false; - } - - switch (value.Type) - { - case JTokenType.Object: - var nestedValues = value.ToObject>(); - return nestedValues?.Any() != true || - nestedValues.All(pair => IsMatch(pair.Value, input.SelectToken(pair.Key))); - - case JTokenType.Array: - var valuesArray = value.ToObject(); - var tokenArray = input.ToObject(); - - if (valuesArray?.Any() != true) - { - return true; - } - - return tokenArray?.Any() == true && - valuesArray.All(subFilter => tokenArray.Any(subToken => IsMatch(subFilter, subToken))); - - default: - return value.ToString() == input.ToString(); - } + var exactStringMatcher = new ExactMatcher(MatchBehaviour.AcceptOnMatch, ThrowException, value); + return MatchScores.IsPerfect(exactStringMatcher.IsMatch(input)); } } } diff --git a/src/WireMock.Net/Matchers/JsonPartialWildCardMatcher.cs b/src/WireMock.Net/Matchers/JsonPartialWildCardMatcher.cs new file mode 100644 index 00000000..5f804150 --- /dev/null +++ b/src/WireMock.Net/Matchers/JsonPartialWildCardMatcher.cs @@ -0,0 +1,38 @@ +using JetBrains.Annotations; + +namespace WireMock.Matchers +{ + /// + /// JsonPartialWildCardMatcher + /// + public class JsonPartialWildcardMatcher : AbstractJsonPartialMatcher + { + /// + public override string Name => nameof(JsonPartialWildcardMatcher); + + /// + public JsonPartialWildcardMatcher([NotNull] string value, bool ignoreCase = false, bool throwException = false) + : base(value, ignoreCase, throwException) + { + } + + /// + public JsonPartialWildcardMatcher([NotNull] object value, bool ignoreCase = false, bool throwException = false) + : base(value, ignoreCase, throwException) + { + } + + /// + public JsonPartialWildcardMatcher(MatchBehaviour matchBehaviour, [NotNull] object value, bool ignoreCase = false, bool throwException = false) + : base(matchBehaviour, value, ignoreCase, throwException) + { + } + + /// + protected override bool IsMatch(string value, string input) + { + var wildcardStringMatcher = new WildcardMatcher(MatchBehaviour.AcceptOnMatch, value, IgnoreCase); + return MatchScores.IsPerfect(wildcardStringMatcher.IsMatch(input)); + } + } +} diff --git a/src/WireMock.Net/Serialization/MatcherMapper.cs b/src/WireMock.Net/Serialization/MatcherMapper.cs index 38b311c7..027d5684 100644 --- a/src/WireMock.Net/Serialization/MatcherMapper.cs +++ b/src/WireMock.Net/Serialization/MatcherMapper.cs @@ -44,7 +44,7 @@ namespace WireMock.Serialization switch (matcherName) { - case "NotNullOrEmptyMatcher": + case nameof(NotNullOrEmptyMatcher): return new NotNullOrEmptyMatcher(matchBehaviour); case "CSharpCodeMatcher": @@ -55,42 +55,46 @@ namespace WireMock.Serialization throw new NotSupportedException("It's not allowed to use the 'CSharpCodeMatcher' because IWireMockServerSettings.AllowCSharpCodeMatcher is not set to 'true'."); - case "LinqMatcher": + case nameof(LinqMatcher): return new LinqMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns); - case "ExactMatcher": + case nameof(ExactMatcher): return new ExactMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns); - case "ExactObjectMatcher": + case nameof(ExactObjectMatcher): return CreateExactObjectMatcher(matchBehaviour, stringPatterns[0], throwExceptionWhenMatcherFails); - case "RegexMatcher": + case nameof(RegexMatcher): return new RegexMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails); - case "JsonMatcher": + case nameof(JsonMatcher): object valueForJsonMatcher = matcher.Pattern ?? matcher.Patterns; return new JsonMatcher(matchBehaviour, valueForJsonMatcher, ignoreCase, throwExceptionWhenMatcherFails); - case "JsonPartialMatcher": + case nameof(JsonPartialMatcher): object valueForJsonPartialMatcher = matcher.Pattern ?? matcher.Patterns; return new JsonPartialMatcher(matchBehaviour, valueForJsonPartialMatcher, ignoreCase, throwExceptionWhenMatcherFails); - case "JsonPathMatcher": + case nameof(JsonPartialWildcardMatcher): + object valueForJsonPartialWilcardMatcher = matcher.Pattern ?? matcher.Patterns; + return new JsonPartialWildcardMatcher(matchBehaviour, valueForJsonPartialWilcardMatcher, ignoreCase, throwExceptionWhenMatcherFails); + + case nameof(JsonPathMatcher): return new JsonPathMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns); - case "JmesPathMatcher": + case nameof(JmesPathMatcher): return new JmesPathMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns); - case "XPathMatcher": + case nameof(XPathMatcher): return new XPathMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns); - case "WildcardMatcher": + case nameof(WildcardMatcher): return new WildcardMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails); - case "ContentTypeMatcher": + case nameof(ContentTypeMatcher): return new ContentTypeMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails); - case "SimMetricsMatcher": + case nameof(SimMetricsMatcher): SimMetricType type = SimMetricType.Levenstein; if (!string.IsNullOrEmpty(matcherType) && !Enum.TryParse(matcherType, out type)) { diff --git a/test/WireMock.Net.Tests/Matchers/JsonPartialWildcardMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/JsonPartialWildcardMatcherTests.cs new file mode 100644 index 00000000..436b197e --- /dev/null +++ b/test/WireMock.Net.Tests/Matchers/JsonPartialWildcardMatcherTests.cs @@ -0,0 +1,400 @@ +using System; +using System.Collections.Generic; +using System.IO; +using FluentAssertions; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using NFluent; +using WireMock.Matchers; +using Xunit; + +namespace WireMock.Net.Tests.Matchers +{ + public class JsonPartialWildcardMatcherTests + { + [Fact] + public void JsonPartialWildcardMatcher_GetName() + { + // Assign + var matcher = new JsonPartialWildcardMatcher("{}"); + + // Act + string name = matcher.Name; + + // Assert + Check.That(name).Equals("JsonPartialWildcardMatcher"); + } + + [Fact] + public void JsonPartialWildcardMatcher_GetValue() + { + // Assign + var matcher = new JsonPartialWildcardMatcher("{}"); + + // Act + object value = matcher.Value; + + // Assert + Check.That(value).Equals("{}"); + } + + [Fact] + public void JsonPartialWildcardMatcher_WithInvalidStringValue_Should_ThrowException() + { + // Act + Action action = () => new JsonPartialWildcardMatcher(MatchBehaviour.AcceptOnMatch, "{ \"Id\""); + + // Assert + action.Should().Throw(); + } + + [Fact] + public void JsonPartialWildcardMatcher_WithInvalidObjectValue_Should_ThrowException() + { + // Act + Action action = () => new JsonPartialWildcardMatcher(MatchBehaviour.AcceptOnMatch, new MemoryStream()); + + // Assert + action.Should().Throw(); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_WithInvalidValue_And_ThrowExceptionIsFalse_Should_ReturnMismatch() + { + // Assign + var matcher = new JsonPartialWildcardMatcher(""); + + // Act + double match = matcher.IsMatch(new MemoryStream()); + + // Assert + Check.That(match).IsEqualTo(0); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_WithInvalidValue_And_ThrowExceptionIsTrue_Should_ReturnMismatch() + { + // Assign + var matcher = new JsonPartialWildcardMatcher("", false, true); + + // Act + Action action = () => matcher.IsMatch(new MemoryStream()); + + // Assert + action.Should().Throw(); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_ByteArray() + { + // Assign + var bytes = new byte[0]; + var matcher = new JsonPartialWildcardMatcher(""); + + // Act + double match = matcher.IsMatch(bytes); + + // Assert + Check.That(match).IsEqualTo(0); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_NullString() + { + // Assign + string s = null; + var matcher = new JsonPartialWildcardMatcher(""); + + // Act + double match = matcher.IsMatch(s); + + // Assert + Check.That(match).IsEqualTo(0); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_NullObject() + { + // Assign + object o = null; + var matcher = new JsonPartialWildcardMatcher(""); + + // Act + double match = matcher.IsMatch(o); + + // Assert + Check.That(match).IsEqualTo(0); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_JArray() + { + // Assign + var matcher = new JsonPartialWildcardMatcher(new[] { "x", "y" }); + + // Act + var jArray = new JArray + { + "x", + "y" + }; + double match = matcher.IsMatch(jArray); + + // Assert + Assert.Equal(1.0, match); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_JObject() + { + // Assign + var matcher = new JsonPartialWildcardMatcher(new { Id = 1, Name = "Test" }); + + // Act + var jobject = new JObject + { + { "Id", new JValue(1) }, + { "Name", new JValue("Test") } + }; + double match = matcher.IsMatch(jobject); + + // Assert + Assert.Equal(1.0, match); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_WithIgnoreCaseTrue_JObject() + { + // Assign + var matcher = new JsonPartialWildcardMatcher(new { id = 1, Name = "test" }, true); + + // Act + var jobject = new JObject + { + { "Id", new JValue(1) }, + { "NaMe", new JValue("Test") } + }; + double match = matcher.IsMatch(jobject); + + // Assert + Assert.Equal(1.0, match); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_JObjectParsed() + { + // Assign + var matcher = new JsonPartialWildcardMatcher(new { Id = 1, Name = "Test" }); + + // Act + var jobject = JObject.Parse("{ \"Id\" : 1, \"Name\" : \"Test\" }"); + double match = matcher.IsMatch(jobject); + + // Assert + Assert.Equal(1.0, match); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_WithIgnoreCaseTrue_JObjectParsed() + { + // Assign + var matcher = new JsonPartialWildcardMatcher(new { Id = 1, Name = "TESt" }, true); + + // Act + var jobject = JObject.Parse("{ \"Id\" : 1, \"Name\" : \"Test\" }"); + double match = matcher.IsMatch(jobject); + + // Assert + Assert.Equal(1.0, match); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_JArrayAsString() + { + // Assign + var matcher = new JsonPartialWildcardMatcher("[ \"x\", \"y\" ]"); + + // Act + var jArray = new JArray + { + "x", + "y" + }; + double match = matcher.IsMatch(jArray); + + // Assert + Assert.Equal(1.0, match); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_JObjectAsString() + { + // Assign + var matcher = new JsonPartialWildcardMatcher("{ \"Id\" : 1, \"Name\" : \"Test\" }"); + + // Act + var jobject = new JObject + { + { "Id", new JValue(1) }, + { "Name", new JValue("Test") } + }; + double match = matcher.IsMatch(jobject); + + // Assert + Assert.Equal(1.0, match); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_WithIgnoreCaseTrue_JObjectAsString() + { + // Assign + var matcher = new JsonPartialWildcardMatcher("{ \"Id\" : 1, \"Name\" : \"test\" }", true); + + // Act + var jobject = new JObject + { + { "Id", new JValue(1) }, + { "Name", new JValue("Test") } + }; + double match = matcher.IsMatch(jobject); + + // Assert + Assert.Equal(1.0, match); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_JObjectAsString_RejectOnMatch() + { + // Assign + var matcher = new JsonPartialWildcardMatcher(MatchBehaviour.RejectOnMatch, "{ \"Id\" : 1, \"Name\" : \"Test\" }"); + + // Act + var jobject = new JObject + { + { "Id", new JValue(1) }, + { "Name", new JValue("Test") } + }; + double match = matcher.IsMatch(jobject); + + // Assert + Assert.Equal(0.0, match); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_JObjectWithDateTimeOffsetAsString() + { + // Assign + var matcher = new JsonPartialWildcardMatcher("{ \"preferredAt\" : \"2019-11-21T10:32:53.2210009+00:00\" }"); + + // Act + var jobject = new JObject + { + { "preferredAt", new JValue("2019-11-21T10:32:53.2210009+00:00") } + }; + double match = matcher.IsMatch(jobject); + + // Assert + Assert.Equal(1.0, match); + } + + [Theory] + [InlineData("{\"test\":\"abc\"}", "{\"test\":\"abc\",\"other\":\"xyz\"}")] + [InlineData("\"test\"", "\"test\"")] + [InlineData("123", "123")] + [InlineData("[\"test\"]", "[\"test\"]")] + [InlineData("[\"test\"]", "[\"test\", \"other\"]")] + [InlineData("[123]", "[123]")] + [InlineData("[123]", "[123, 456]")] + [InlineData("{ \"test\":\"value\" }", "{\"test\":\"value\",\"other\":123}")] + [InlineData("{ \"test\":\"value\" }", "{\"test\":\"value\"}")] + [InlineData("{\"test\":{\"nested\":\"value\"}}", "{\"test\":{\"nested\":\"value\"}}")] + public void JsonPartialWildcardMatcher_IsMatch_StringInput_IsValidMatch(string value, string input) + { + // Assign + var matcher = new JsonPartialWildcardMatcher(value); + + // Act + double match = matcher.IsMatch(input); + + // Assert + Assert.Equal(1.0, match); + } + + [Theory] + [InlineData("{\"test\":\"*\"}", "{\"test\":\"xxx\",\"other\":\"xyz\"}")] + [InlineData("\"t*t\"", "\"test\"")] + public void JsonPartialWildcardMatcher_IsMatch_StringInputWithWildcard_IsValidMatch(string value, string input) + { + // Assign + var matcher = new JsonPartialWildcardMatcher(value); + + // Act + double match = matcher.IsMatch(input); + + // Assert + match.Should().Be(1.0); + } + + [Theory] + [InlineData("\"test\"", null)] + [InlineData("\"test1\"", "\"test2\"")] + [InlineData("123", "1234")] + [InlineData("[\"test\"]", "[\"test1\"]")] + [InlineData("[\"test\"]", "[\"test1\", \"test2\"]")] + [InlineData("[123]", "[1234]")] + [InlineData("{}", "\"test\"")] + [InlineData("{ \"test\":\"value\" }", "{\"test\":\"value2\"}")] + [InlineData("{ \"test.nested\":\"value\" }", "{\"test\":{\"nested\":\"value1\"}}")] + [InlineData("{\"test\":{\"test1\":\"value\"}}", "{\"test\":{\"test1\":\"value1\"}}")] + [InlineData("[{ \"test.nested\":\"value\" }]", "[{\"test\":{\"nested\":\"value1\"}}]")] + public void JsonPartialWildcardMatcher_IsMatch_StringInputWithInvalidMatch(string value, string input) + { + // Assign + var matcher = new JsonPartialWildcardMatcher(value); + + // Act + double match = matcher.IsMatch(input); + + // Assert + Assert.Equal(0.0, match); + } + + [Theory] + [InlineData("{ \"test.nested\":123 }", "{\"test\":{\"nested\":123}}")] + [InlineData("{ \"test.nested\":[123, 456] }", "{\"test\":{\"nested\":[123, 456]}}")] + [InlineData("{ \"test.nested\":\"value\" }", "{\"test\":{\"nested\":\"value\"}}")] + [InlineData("{ \"['name.with.dot']\":\"value\" }", "{\"name.with.dot\":\"value\"}")] + [InlineData("[{ \"test.nested\":\"value\" }]", "[{\"test\":{\"nested\":\"value\"}}]")] + [InlineData("[{ \"['name.with.dot']\":\"value\" }]", "[{\"name.with.dot\":\"value\"}]")] + public void JsonPartialWildcardMatcher_IsMatch_ValueAsJPathValidMatch(string value, string input) + { + // Assign + var matcher = new JsonPartialWildcardMatcher(value); + + // Act + double match = matcher.IsMatch(input); + + // Assert + Assert.Equal(1.0, match); + } + + [Theory] + [InlineData("{ \"test.nested\":123 }", "{\"test\":{\"nested\":456}}")] + [InlineData("{ \"test.nested\":[123, 456] }", "{\"test\":{\"nested\":[1, 2]}}")] + [InlineData("{ \"test.nested\":\"value\" }", "{\"test\":{\"nested\":\"value1\"}}")] + [InlineData("{ \"['name.with.dot']\":\"value\" }", "{\"name.with.dot\":\"value1\"}")] + [InlineData("[{ \"test.nested\":\"value\" }]", "[{\"test\":{\"nested\":\"value1\"}}]")] + [InlineData("[{ \"['name.with.dot']\":\"value\" }]", "[{\"name.with.dot\":\"value1\"}]")] + public void JsonPartialWildcardMatcher_IsMatch_ValueAsJPathInvalidMatch(string value, string input) + { + // Assign + var matcher = new JsonPartialWildcardMatcher(value); + + // Act + double match = matcher.IsMatch(input); + + // Assert + Assert.Equal(0.0, match); + } + } +} diff --git a/test/WireMock.Net.Tests/Serialization/MatcherMapperTests.cs b/test/WireMock.Net.Tests/Serialization/MatcherMapperTests.cs index 18254ea1..bb3b67bd 100644 --- a/test/WireMock.Net.Tests/Serialization/MatcherMapperTests.cs +++ b/test/WireMock.Net.Tests/Serialization/MatcherMapperTests.cs @@ -345,5 +345,24 @@ namespace WireMock.Net.Tests.Serialization matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); matcher.Value.Should().BeEquivalentTo(pattern); } + + [Fact] + public void MatcherMapper_Map_MatcherModel_JsonPartialWilcardMatcher_Patterns_As_Object() + { + // Assign + object pattern = new { X = "*" }; + var model = new MatcherModel + { + Name = "JsonPartialWildcardMatcher", + Pattern = pattern + }; + + // Act + var matcher = (JsonPartialWildcardMatcher)_sut.Map(model); + + // Assert + matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); + matcher.Value.Should().BeEquivalentTo(pattern); + } } }