From 0f99e06accc405a88402ac49aabc9a84b8ee62a5 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Wed, 4 Aug 2021 16:22:22 +0200 Subject: [PATCH] Add NotNullOrEmptyMatcher (#625) --- .editorconfig | 6 + Directory.Build.props | 2 +- WireMock.Net Solution.sln | 5 +- src/WireMock.Net/Matchers/IValueMatcher.cs | 28 +- .../Matchers/NotNullOrEmptyMatcher.cs | 52 ++ src/WireMock.Net/Matchers/RegexMatcher.cs | 220 +++--- .../Request/RequestMessageBodyMatcher.cs | 16 + .../Serialization/MatcherMapper.cs | 7 +- .../Matchers/NotNullOrEmptyMatcherTests.cs | 60 ++ .../RequestMessageBodyMatcherTests.cs | 705 ++++++++++-------- .../Serialization/MatcherModelMapperTests.cs | 544 +++++++------- 11 files changed, 916 insertions(+), 729 deletions(-) create mode 100644 .editorconfig create mode 100644 src/WireMock.Net/Matchers/NotNullOrEmptyMatcher.cs create mode 100644 test/WireMock.Net.Tests/Matchers/NotNullOrEmptyMatcherTests.cs diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..0d64ba1e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,6 @@ +[*] +indent_style = space +indent_size = 4 +end_of_line = crlf +charset = utf-8 +trim_trailing_whitespace = true \ No newline at end of file diff --git a/Directory.Build.props b/Directory.Build.props index 9cef6c08..a881fee8 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,7 +4,7 @@ - 1.4.19-preview-01 + 1.4.19 See CHANGELOG.md https://raw.githubusercontent.com/WireMock-Net/WireMock.Net/master/WireMock.Net-Logo.png https://github.com/WireMock-Net/WireMock.Net diff --git a/WireMock.Net Solution.sln b/WireMock.Net Solution.sln index 5e5ab385..1131cf4c 100644 --- a/WireMock.Net Solution.sln +++ b/WireMock.Net Solution.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30114.105 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31521.260 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{8F890C6F-9ACC-438D-928A-AD61CDA862F2}" EndProject @@ -21,6 +21,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{98 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7EFB2C5B-1BB2-4AAF-BC9F-216ED80C594D}" ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig .gitignore = .gitignore azure-pipelines-ci-linux.yml = azure-pipelines-ci-linux.yml azure-pipelines-ci.yml = azure-pipelines-ci.yml diff --git a/src/WireMock.Net/Matchers/IValueMatcher.cs b/src/WireMock.Net/Matchers/IValueMatcher.cs index 503068a7..33151459 100644 --- a/src/WireMock.Net/Matchers/IValueMatcher.cs +++ b/src/WireMock.Net/Matchers/IValueMatcher.cs @@ -1,15 +1,15 @@ -namespace WireMock.Matchers -{ - /// - /// IValueMatcher - /// - /// - public interface IValueMatcher: IObjectMatcher - { - /// - /// Gets the value (can be a string or an object). - /// - /// Value - object Value { get; } - } +namespace WireMock.Matchers +{ + /// + /// IValueMatcher + /// + /// + public interface IValueMatcher : IObjectMatcher + { + /// + /// Gets the value (can be a string or an object). + /// + /// Value + object Value { get; } + } } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/NotNullOrEmptyMatcher.cs b/src/WireMock.Net/Matchers/NotNullOrEmptyMatcher.cs new file mode 100644 index 00000000..00354933 --- /dev/null +++ b/src/WireMock.Net/Matchers/NotNullOrEmptyMatcher.cs @@ -0,0 +1,52 @@ +using System.Linq; + +namespace WireMock.Matchers +{ + /// + /// NotNullOrEmptyMatcher + /// + /// + public class NotNullOrEmptyMatcher : IObjectMatcher + { + /// + public string Name => "NotNullOrEmptyMatcher"; + + /// + public MatchBehaviour MatchBehaviour { get; } + + /// + public bool ThrowException { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + public NotNullOrEmptyMatcher(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + MatchBehaviour = matchBehaviour; + } + + /// + public double IsMatch(object input) + { + bool match; + + switch (input) + { + case string @string: + match = !string.IsNullOrEmpty(@string); + break; + + case byte[] bytes: + match = bytes != null && bytes.Any(); + break; + + default: + match = input != null; + break; + } + + return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(match)); + } + } +} \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/RegexMatcher.cs b/src/WireMock.Net/Matchers/RegexMatcher.cs index a5b52b55..f0c22bac 100644 --- a/src/WireMock.Net/Matchers/RegexMatcher.cs +++ b/src/WireMock.Net/Matchers/RegexMatcher.cs @@ -1,113 +1,113 @@ -using System; -using System.Linq; -using System.Text.RegularExpressions; -using JetBrains.Annotations; -using WireMock.Validation; - -namespace WireMock.Matchers -{ - /// - /// Regular Expression Matcher - /// - /// - /// - public class RegexMatcher : IStringMatcher, IIgnoreCaseMatcher - { - private readonly string[] _patterns; - private readonly Regex[] _expressions; - - /// - public MatchBehaviour MatchBehaviour { get; } - - /// - public bool ThrowException { get; } - - /// - /// Initializes a new instance of the class. - /// - /// The pattern. - /// Ignore the case from the pattern. - public RegexMatcher([NotNull, RegexPattern] string pattern, bool ignoreCase = false) : this(new[] { pattern }, ignoreCase) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The match behaviour. - /// The pattern. - /// Ignore the case from the pattern. - public RegexMatcher(MatchBehaviour matchBehaviour, [NotNull, RegexPattern] string pattern, bool ignoreCase = false) : this(matchBehaviour, new[] { pattern }, ignoreCase) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The patterns. - /// Ignore the case from the pattern. - public RegexMatcher([NotNull, RegexPattern] string[] patterns, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, patterns, ignoreCase) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The match behaviour. - /// The patterns. - /// Ignore the case from the pattern. - /// Throw an exception when the internal matching fails because of invalid input. - public RegexMatcher(MatchBehaviour matchBehaviour, [NotNull, RegexPattern] string[] patterns, bool ignoreCase = false, bool throwException = false) - { - Check.NotNull(patterns, nameof(patterns)); - - _patterns = patterns; - IgnoreCase = ignoreCase; - MatchBehaviour = matchBehaviour; - ThrowException = throwException; - - RegexOptions options = RegexOptions.Compiled | RegexOptions.Multiline; - - if (ignoreCase) - { - options |= RegexOptions.IgnoreCase; - } - - _expressions = patterns.Select(p => new Regex(p, options)).ToArray(); - } - - /// - public virtual double IsMatch(string input) - { - double match = MatchScores.Mismatch; - if (input != null) - { - try - { - match = MatchScores.ToScore(_expressions.Select(e => e.IsMatch(input))); - } - catch (Exception) - { - if (ThrowException) - { - throw; - } - } +using System; +using System.Linq; +using System.Text.RegularExpressions; +using JetBrains.Annotations; +using WireMock.Validation; + +namespace WireMock.Matchers +{ + /// + /// Regular Expression Matcher + /// + /// + /// + public class RegexMatcher : IStringMatcher, IIgnoreCaseMatcher + { + private readonly string[] _patterns; + private readonly Regex[] _expressions; + + /// + public MatchBehaviour MatchBehaviour { get; } + + /// + public bool ThrowException { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The pattern. + /// Ignore the case from the pattern. + public RegexMatcher([NotNull, RegexPattern] string pattern, bool ignoreCase = false) : this(new[] { pattern }, ignoreCase) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The pattern. + /// Ignore the case from the pattern. + public RegexMatcher(MatchBehaviour matchBehaviour, [NotNull, RegexPattern] string pattern, bool ignoreCase = false) : this(matchBehaviour, new[] { pattern }, ignoreCase) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The patterns. + /// Ignore the case from the pattern. + public RegexMatcher([NotNull, RegexPattern] string[] patterns, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, patterns, ignoreCase) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The patterns. + /// Ignore the case from the pattern. + /// Throw an exception when the internal matching fails because of invalid input. + public RegexMatcher(MatchBehaviour matchBehaviour, [NotNull, RegexPattern] string[] patterns, bool ignoreCase = false, bool throwException = false) + { + Check.NotNull(patterns, nameof(patterns)); + + _patterns = patterns; + IgnoreCase = ignoreCase; + MatchBehaviour = matchBehaviour; + ThrowException = throwException; + + RegexOptions options = RegexOptions.Compiled | RegexOptions.Multiline; + + if (ignoreCase) + { + options |= RegexOptions.IgnoreCase; } - return MatchBehaviourHelper.Convert(MatchBehaviour, match); - } - - /// - public virtual string[] GetPatterns() - { - return _patterns; - } - - /// - public virtual string Name => "RegexMatcher"; - - /// - public bool IgnoreCase { get; } - } + _expressions = patterns.Select(p => new Regex(p, options)).ToArray(); + } + + /// + public virtual double IsMatch(string input) + { + double match = MatchScores.Mismatch; + if (input != null) + { + try + { + match = MatchScores.ToScore(_expressions.Select(e => e.IsMatch(input))); + } + catch (Exception) + { + if (ThrowException) + { + throw; + } + } + } + + return MatchBehaviourHelper.Convert(MatchBehaviour, match); + } + + /// + public virtual string[] GetPatterns() + { + return _patterns; + } + + /// + public virtual string Name => "RegexMatcher"; + + /// + public bool IgnoreCase { get; } + } } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageBodyMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageBodyMatcher.cs index d891bc7d..89df34ff 100644 --- a/src/WireMock.Net/Matchers/Request/RequestMessageBodyMatcher.cs +++ b/src/WireMock.Net/Matchers/Request/RequestMessageBodyMatcher.cs @@ -123,6 +123,22 @@ namespace WireMock.Matchers.Request private double CalculateMatchScore(IRequestMessage requestMessage, IMatcher matcher) { + if (matcher is NotNullOrEmptyMatcher notNullOrEmptyMatcher) + { + switch (requestMessage?.BodyData?.DetectedBodyType) + { + case BodyType.Json: + case BodyType.String: + return notNullOrEmptyMatcher.IsMatch(requestMessage.BodyData.BodyAsString); + + case BodyType.Bytes: + return notNullOrEmptyMatcher.IsMatch(requestMessage.BodyData.BodyAsBytes); + + default: + return MatchScores.Mismatch; + } + } + if (matcher is ExactObjectMatcher exactObjectMatcher) { // If the body is a byte array, try to match. diff --git a/src/WireMock.Net/Serialization/MatcherMapper.cs b/src/WireMock.Net/Serialization/MatcherMapper.cs index 4d369779..bea5df7e 100644 --- a/src/WireMock.Net/Serialization/MatcherMapper.cs +++ b/src/WireMock.Net/Serialization/MatcherMapper.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; @@ -43,7 +43,10 @@ namespace WireMock.Serialization bool throwExceptionWhenMatcherFails = _settings.ThrowExceptionWhenMatcherFails == true; switch (matcherName) - { + { + case "NotNullOrEmptyMatcher": + return new NotNullOrEmptyMatcher(matchBehaviour); + case "CSharpCodeMatcher": if (_settings.AllowCSharpCodeMatcher == true) { diff --git a/test/WireMock.Net.Tests/Matchers/NotNullOrEmptyMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/NotNullOrEmptyMatcherTests.cs new file mode 100644 index 00000000..ca5c7242 --- /dev/null +++ b/test/WireMock.Net.Tests/Matchers/NotNullOrEmptyMatcherTests.cs @@ -0,0 +1,60 @@ +using FluentAssertions; +using NFluent; +using WireMock.Matchers; +using Xunit; + +namespace WireMock.Net.Tests.Matchers +{ + public class NotNullOrEmptyMatcherTests + { + [Fact] + public void NotNullOrEmptyMatcher_GetName() + { + // Act + var matcher = new NotNullOrEmptyMatcher(); + string name = matcher.Name; + + // Assert + Check.That(name).Equals("NotNullOrEmptyMatcher"); + } + + [Theory] + [InlineData(null, 0.0)] + [InlineData(new byte[0], 0.0)] + [InlineData(new byte[] { 48 }, 1.0)] + public void NotNullOrEmptyMatcher_IsMatch_ByteArray(byte[] data, double expected) + { + // Act + var matcher = new NotNullOrEmptyMatcher(); + double result = matcher.IsMatch(data); + + // Assert + result.Should().Be(expected); + } + + [Theory] + [InlineData(null, 0.0)] + [InlineData("", 0.0)] + [InlineData("x", 1.0)] + public void NotNullOrEmptyMatcher_IsMatch_String(string data, double expected) + { + // Act + var matcher = new NotNullOrEmptyMatcher(); + double result = matcher.IsMatch(data); + + // Assert + result.Should().Be(expected); + } + + [Fact] + public void NotNullOrEmptyMatcher_IsMatch_Json() + { + // Act + var matcher = new NotNullOrEmptyMatcher(); + double result = matcher.IsMatch(new { x = "x" }); + + // Assert + result.Should().Be(1.0); + } + } +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/RequestMatchers/RequestMessageBodyMatcherTests.cs b/test/WireMock.Net.Tests/RequestMatchers/RequestMessageBodyMatcherTests.cs index 43a1e298..8573bc2d 100644 --- a/test/WireMock.Net.Tests/RequestMatchers/RequestMessageBodyMatcherTests.cs +++ b/test/WireMock.Net.Tests/RequestMatchers/RequestMessageBodyMatcherTests.cs @@ -1,328 +1,377 @@ -using System; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Moq; -using NFluent; -using WireMock.Matchers; -using WireMock.Matchers.Request; -using WireMock.Models; -using WireMock.Types; -using WireMock.Util; -using Xunit; - -namespace WireMock.Net.Tests.RequestMatchers -{ - public class RequestMessageBodyMatcherTests - { - [Fact] - public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsString_IStringMatcher() - { - // Assign - var body = new BodyData - { - BodyAsString = "b", - DetectedBodyType = BodyType.String - }; - var stringMatcherMock = new Mock(); - stringMatcherMock.Setup(m => m.IsMatch(It.IsAny())).Returns(0.5d); - - var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); - - var matcher = new RequestMessageBodyMatcher(stringMatcherMock.Object); - - // Act - var result = new RequestMatchResult(); - double score = matcher.GetMatchingScore(requestMessage, result); - - // Assert - Check.That(score).IsEqualTo(0.5d); - - // Verify - stringMatcherMock.Verify(m => m.GetPatterns(), Times.Never); - stringMatcherMock.Verify(m => m.IsMatch("b"), Times.Once); - } - - [Fact] - public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsString_IStringMatchers() - { - // Assign - var body = new BodyData - { - BodyAsString = "b", - DetectedBodyType = BodyType.String - }; - var stringMatcherMock1 = new Mock(); - stringMatcherMock1.Setup(m => m.IsMatch(It.IsAny())).Returns(0.2d); - var stringMatcherMock2 = new Mock(); - stringMatcherMock2.Setup(m => m.IsMatch(It.IsAny())).Returns(0.8d); - var matchers = new[] { stringMatcherMock1.Object, stringMatcherMock2.Object }; - - var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); - - var matcher = new RequestMessageBodyMatcher(matchers.Cast().ToArray()); - - // Act - var result = new RequestMatchResult(); - double score = matcher.GetMatchingScore(requestMessage, result); - - // Assert - Check.That(score).IsEqualTo(0.8d); - - // Verify - stringMatcherMock1.Verify(m => m.GetPatterns(), Times.Never); - stringMatcherMock1.Verify(m => m.IsMatch("b"), Times.Once); - stringMatcherMock2.Verify(m => m.GetPatterns(), Times.Never); - stringMatcherMock2.Verify(m => m.IsMatch("b"), Times.Once); - } - - [Fact] - public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsBytes_IStringMatcher() - { - // Assign - var body = new BodyData - { - BodyAsBytes = new byte[] { 1 }, - DetectedBodyType = BodyType.Bytes - }; - var stringMatcherMock = new Mock(); - stringMatcherMock.Setup(m => m.IsMatch(It.IsAny())).Returns(0.5d); - - var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); - - var matcher = new RequestMessageBodyMatcher(stringMatcherMock.Object); - - // Act - var result = new RequestMatchResult(); - double score = matcher.GetMatchingScore(requestMessage, result); - - // Assert - Check.That(score).IsEqualTo(0.0d); - - // Verify - stringMatcherMock.Verify(m => m.GetPatterns(), Times.Never); - stringMatcherMock.Verify(m => m.IsMatch(It.IsAny()), Times.Never); - } - - [Fact] - public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsJson_IStringMatcher() - { - // Assign - var body = new BodyData - { - BodyAsJson = new { value = 42 }, - DetectedBodyType = BodyType.Json - }; - var stringMatcherMock = new Mock(); - stringMatcherMock.Setup(m => m.IsMatch(It.IsAny())).Returns(0.5d); - - var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); - - var matcher = new RequestMessageBodyMatcher(stringMatcherMock.Object); - - // Act - var result = new RequestMatchResult(); - double score = matcher.GetMatchingScore(requestMessage, result); - - // Assert - Check.That(score).IsEqualTo(0.5d); - - // Verify - stringMatcherMock.Verify(m => m.IsMatch(It.IsAny()), Times.Once); - } - - [Fact] - public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsJson_and_BodyAsString_IStringMatcher() - { - // Assign - var body = new BodyData - { - BodyAsJson = new { value = 42 }, - BodyAsString = "orig", - DetectedBodyType = BodyType.Json - }; - var stringMatcherMock = new Mock(); - stringMatcherMock.Setup(m => m.IsMatch(It.IsAny())).Returns(0.5d); - - var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); - - var matcher = new RequestMessageBodyMatcher(stringMatcherMock.Object); - - // Act - var result = new RequestMatchResult(); - double score = matcher.GetMatchingScore(requestMessage, result); - - // Assert - Check.That(score).IsEqualTo(0.5d); - - // Verify - stringMatcherMock.Verify(m => m.IsMatch(It.IsAny()), Times.Once); - } - - [Fact] - public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsJson_IObjectMatcher() - { - // Assign - var body = new BodyData - { - BodyAsJson = 42, - DetectedBodyType = BodyType.Json - }; - var objectMatcherMock = new Mock(); - objectMatcherMock.Setup(m => m.IsMatch(It.IsAny())).Returns(0.5d); - - var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); - - var matcher = new RequestMessageBodyMatcher(objectMatcherMock.Object); - - // Act - var result = new RequestMatchResult(); - double score = matcher.GetMatchingScore(requestMessage, result); - - // Assert - Check.That(score).IsEqualTo(0.5d); - - // Verify - objectMatcherMock.Verify(m => m.IsMatch(42), Times.Once); - } - - [Fact] - public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsJson_CSharpCodeMatcher() - { - // Assign - var body = new BodyData - { - BodyAsJson = new { value = 42 }, - DetectedBodyType = BodyType.Json - }; - - var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); - - var matcher = new RequestMessageBodyMatcher(new CSharpCodeMatcher(MatchBehaviour.AcceptOnMatch, "return it.value == 42;")); - - // Act - var result = new RequestMatchResult(); - double score = matcher.GetMatchingScore(requestMessage, result); - - // Assert - Check.That(score).IsEqualTo(1.0d); - } - - [Theory] - [InlineData(new byte[] { 1 })] - [InlineData(new byte[] { 48 })] - public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsBytes_IObjectMatcher(byte[] bytes) - { - // Assign - var body = new BodyData - { - BodyAsBytes = bytes, - DetectedBodyType = BodyType.Bytes - }; - var objectMatcherMock = new Mock(); - objectMatcherMock.Setup(m => m.IsMatch(It.IsAny())).Returns(0.5d); - - var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); - - var matcher = new RequestMessageBodyMatcher(objectMatcherMock.Object); - - // Act - var result = new RequestMatchResult(); - double score = matcher.GetMatchingScore(requestMessage, result); - - // Assert - Check.That(score).IsEqualTo(0.5d); - - // Verify - objectMatcherMock.Verify(m => m.IsMatch(It.IsAny()), Times.Once); - } - - [Theory] - [MemberData(nameof(MatchingScoreData))] - public async Task RequestMessageBodyMatcher_GetMatchingScore_Funcs_Matching(object body, RequestMessageBodyMatcher matcher, bool shouldMatch) - { - // assign - BodyData bodyData; - if (body is byte[] b) - { - var bodyParserSettings = new BodyParserSettings - { - Stream = new MemoryStream(b), - ContentType = null, - DeserializeJson = true - }; - bodyData = await BodyParser.Parse(bodyParserSettings); - } - else if (body is string s) - { - var bodyParserSettings = new BodyParserSettings - { - Stream = new MemoryStream(Encoding.UTF8.GetBytes(s)), - ContentType = null, - DeserializeJson = true - }; - bodyData = await BodyParser.Parse(bodyParserSettings); - } - else - { - throw new Exception(); - } - - var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", bodyData); - - // act - var result = new RequestMatchResult(); - var score = matcher.GetMatchingScore(requestMessage, result); - - // assert - Check.That(score).IsEqualTo(shouldMatch ? 1d : 0d); - } - - public static TheoryData MatchingScoreData - { - get - { - var json = "{'a':'b'}"; - var str = "HelloWorld"; - var bytes = new byte[] { 0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00 }; - - return new TheoryData - { - // JSON match +++ - {json, new RequestMessageBodyMatcher((object o) => ((dynamic) o).a == "b"), true}, - {json, new RequestMessageBodyMatcher((string s) => s == json), true}, - {json, new RequestMessageBodyMatcher((byte[] b) => b.SequenceEqual(Encoding.UTF8.GetBytes(json))), true}, - - // JSON no match --- - {json, new RequestMessageBodyMatcher((object o) => false), false}, - {json, new RequestMessageBodyMatcher((string s) => false), false}, - {json, new RequestMessageBodyMatcher((byte[] b) => false), false}, - {json, new RequestMessageBodyMatcher(), false }, - - // string match +++ - {str, new RequestMessageBodyMatcher((object o) => o == null), true}, - {str, new RequestMessageBodyMatcher((string s) => s == str), true}, - {str, new RequestMessageBodyMatcher((byte[] b) => b.SequenceEqual(Encoding.UTF8.GetBytes(str))), true}, - - // string no match --- - {str, new RequestMessageBodyMatcher((object o) => false), false}, - {str, new RequestMessageBodyMatcher((string s) => false), false}, - {str, new RequestMessageBodyMatcher((byte[] b) => false), false}, - {str, new RequestMessageBodyMatcher(), false }, - - // binary match +++ - {bytes, new RequestMessageBodyMatcher((object o) => o == null), true}, - {bytes, new RequestMessageBodyMatcher((string s) => s == null), true}, - {bytes, new RequestMessageBodyMatcher((byte[] b) => b.SequenceEqual(bytes)), true}, - - // binary no match --- - {bytes, new RequestMessageBodyMatcher((object o) => false), false}, - {bytes, new RequestMessageBodyMatcher((string s) => false), false}, - {bytes, new RequestMessageBodyMatcher((byte[] b) => false), false}, - {bytes, new RequestMessageBodyMatcher(), false }, - }; - } - } - } -} +using System; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FluentAssertions; +using Moq; +using NFluent; +using WireMock.Matchers; +using WireMock.Matchers.Request; +using WireMock.Models; +using WireMock.Types; +using WireMock.Util; +using Xunit; + +namespace WireMock.Net.Tests.RequestMatchers +{ + public class RequestMessageBodyMatcherTests + { + [Fact] + public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsString_IStringMatcher() + { + // Assign + var body = new BodyData + { + BodyAsString = "b", + DetectedBodyType = BodyType.String + }; + var stringMatcherMock = new Mock(); + stringMatcherMock.Setup(m => m.IsMatch(It.IsAny())).Returns(0.5d); + + var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); + + var matcher = new RequestMessageBodyMatcher(stringMatcherMock.Object); + + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); + + // Assert + Check.That(score).IsEqualTo(0.5d); + + // Verify + stringMatcherMock.Verify(m => m.GetPatterns(), Times.Never); + stringMatcherMock.Verify(m => m.IsMatch("b"), Times.Once); + } + + [Fact] + public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsString_IStringMatchers() + { + // Assign + var body = new BodyData + { + BodyAsString = "b", + DetectedBodyType = BodyType.String + }; + var stringMatcherMock1 = new Mock(); + stringMatcherMock1.Setup(m => m.IsMatch(It.IsAny())).Returns(0.2d); + var stringMatcherMock2 = new Mock(); + stringMatcherMock2.Setup(m => m.IsMatch(It.IsAny())).Returns(0.8d); + var matchers = new[] { stringMatcherMock1.Object, stringMatcherMock2.Object }; + + var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); + + var matcher = new RequestMessageBodyMatcher(matchers.Cast().ToArray()); + + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); + + // Assert + Check.That(score).IsEqualTo(0.8d); + + // Verify + stringMatcherMock1.Verify(m => m.GetPatterns(), Times.Never); + stringMatcherMock1.Verify(m => m.IsMatch("b"), Times.Once); + stringMatcherMock2.Verify(m => m.GetPatterns(), Times.Never); + stringMatcherMock2.Verify(m => m.IsMatch("b"), Times.Once); + } + + [Fact] + public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsBytes_IStringMatcher() + { + // Assign + var body = new BodyData + { + BodyAsBytes = new byte[] { 1 }, + DetectedBodyType = BodyType.Bytes + }; + var stringMatcherMock = new Mock(); + stringMatcherMock.Setup(m => m.IsMatch(It.IsAny())).Returns(0.5d); + + var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); + + var matcher = new RequestMessageBodyMatcher(stringMatcherMock.Object); + + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); + + // Assert + Check.That(score).IsEqualTo(0.0d); + + // Verify + stringMatcherMock.Verify(m => m.GetPatterns(), Times.Never); + stringMatcherMock.Verify(m => m.IsMatch(It.IsAny()), Times.Never); + } + + [Fact] + public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsJson_IStringMatcher() + { + // Assign + var body = new BodyData + { + BodyAsJson = new { value = 42 }, + DetectedBodyType = BodyType.Json + }; + var stringMatcherMock = new Mock(); + stringMatcherMock.Setup(m => m.IsMatch(It.IsAny())).Returns(0.5d); + + var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); + + var matcher = new RequestMessageBodyMatcher(stringMatcherMock.Object); + + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); + + // Assert + Check.That(score).IsEqualTo(0.5d); + + // Verify + stringMatcherMock.Verify(m => m.IsMatch(It.IsAny()), Times.Once); + } + + [Fact] + public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsJson_and_BodyAsString_IStringMatcher() + { + // Assign + var body = new BodyData + { + BodyAsJson = new { value = 42 }, + BodyAsString = "orig", + DetectedBodyType = BodyType.Json + }; + var stringMatcherMock = new Mock(); + stringMatcherMock.Setup(m => m.IsMatch(It.IsAny())).Returns(0.5d); + + var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); + + var matcher = new RequestMessageBodyMatcher(stringMatcherMock.Object); + + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); + + // Assert + Check.That(score).IsEqualTo(0.5d); + + // Verify + stringMatcherMock.Verify(m => m.IsMatch(It.IsAny()), Times.Once); + } + + [Fact] + public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsJson_IObjectMatcher() + { + // Assign + var body = new BodyData + { + BodyAsJson = 42, + DetectedBodyType = BodyType.Json + }; + var objectMatcherMock = new Mock(); + objectMatcherMock.Setup(m => m.IsMatch(It.IsAny())).Returns(0.5d); + + var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); + + var matcher = new RequestMessageBodyMatcher(objectMatcherMock.Object); + + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); + + // Assert + Check.That(score).IsEqualTo(0.5d); + + // Verify + objectMatcherMock.Verify(m => m.IsMatch(42), Times.Once); + } + + [Fact] + public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsJson_CSharpCodeMatcher() + { + // Assign + var body = new BodyData + { + BodyAsJson = new { value = 42 }, + DetectedBodyType = BodyType.Json + }; + + var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); + + var matcher = new RequestMessageBodyMatcher(new CSharpCodeMatcher(MatchBehaviour.AcceptOnMatch, "return it.value == 42;")); + + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); + + // Assert + Check.That(score).IsEqualTo(1.0d); + } + + [Theory] + [InlineData(null, 0.0)] + [InlineData(new byte[0], 0.0)] + [InlineData(new byte[] { 48 }, 1.0)] + public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsBytes_NotNullOrEmptyObjectMatcher(byte[] bytes, double expected) + { + // Assign + var body = new BodyData + { + BodyAsBytes = bytes, + DetectedBodyType = BodyType.Bytes + }; + var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); + + var matcher = new RequestMessageBodyMatcher(new NotNullOrEmptyMatcher()); + + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); + + // Assert + score.Should().Be(expected); + } + + [Theory] + [InlineData(null, 0.0)] + [InlineData("", 0.0)] + [InlineData("x", 1.0)] + public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsString_NotNullOrEmptyObjectMatcher(string data, double expected) + { + // Assign + var body = new BodyData + { + BodyAsString = data, + DetectedBodyType = BodyType.String + }; + var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); + + var matcher = new RequestMessageBodyMatcher(new NotNullOrEmptyMatcher()); + + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); + + // Assert + score.Should().Be(expected); + } + + [Theory] + [InlineData(new byte[] { 1 })] + [InlineData(new byte[] { 48 })] + public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsBytes_IObjectMatcher(byte[] bytes) + { + // Assign + var body = new BodyData + { + BodyAsBytes = bytes, + DetectedBodyType = BodyType.Bytes + }; + var objectMatcherMock = new Mock(); + objectMatcherMock.Setup(m => m.IsMatch(It.IsAny())).Returns(0.5d); + + var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); + + var matcher = new RequestMessageBodyMatcher(objectMatcherMock.Object); + + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); + + // Assert + Check.That(score).IsEqualTo(0.5d); + + // Verify + objectMatcherMock.Verify(m => m.IsMatch(It.IsAny()), Times.Once); + } + + [Theory] + [MemberData(nameof(MatchingScoreData))] + public async Task RequestMessageBodyMatcher_GetMatchingScore_Funcs_Matching(object body, RequestMessageBodyMatcher matcher, bool shouldMatch) + { + // assign + BodyData bodyData; + if (body is byte[] b) + { + var bodyParserSettings = new BodyParserSettings + { + Stream = new MemoryStream(b), + ContentType = null, + DeserializeJson = true + }; + bodyData = await BodyParser.Parse(bodyParserSettings); + } + else if (body is string s) + { + var bodyParserSettings = new BodyParserSettings + { + Stream = new MemoryStream(Encoding.UTF8.GetBytes(s)), + ContentType = null, + DeserializeJson = true + }; + bodyData = await BodyParser.Parse(bodyParserSettings); + } + else + { + throw new Exception(); + } + + var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", bodyData); + + // act + var result = new RequestMatchResult(); + var score = matcher.GetMatchingScore(requestMessage, result); + + // assert + Check.That(score).IsEqualTo(shouldMatch ? 1d : 0d); + } + + public static TheoryData MatchingScoreData + { + get + { + var json = "{'a':'b'}"; + var str = "HelloWorld"; + var bytes = new byte[] { 0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00 }; + + return new TheoryData + { + // JSON match +++ + {json, new RequestMessageBodyMatcher((object o) => ((dynamic) o).a == "b"), true}, + {json, new RequestMessageBodyMatcher((string s) => s == json), true}, + {json, new RequestMessageBodyMatcher((byte[] b) => b.SequenceEqual(Encoding.UTF8.GetBytes(json))), true}, + + // JSON no match --- + {json, new RequestMessageBodyMatcher((object o) => false), false}, + {json, new RequestMessageBodyMatcher((string s) => false), false}, + {json, new RequestMessageBodyMatcher((byte[] b) => false), false}, + {json, new RequestMessageBodyMatcher(), false }, + + // string match +++ + {str, new RequestMessageBodyMatcher((object o) => o == null), true}, + {str, new RequestMessageBodyMatcher((string s) => s == str), true}, + {str, new RequestMessageBodyMatcher((byte[] b) => b.SequenceEqual(Encoding.UTF8.GetBytes(str))), true}, + + // string no match --- + {str, new RequestMessageBodyMatcher((object o) => false), false}, + {str, new RequestMessageBodyMatcher((string s) => false), false}, + {str, new RequestMessageBodyMatcher((byte[] b) => false), false}, + {str, new RequestMessageBodyMatcher(), false }, + + // binary match +++ + {bytes, new RequestMessageBodyMatcher((object o) => o == null), true}, + {bytes, new RequestMessageBodyMatcher((string s) => s == null), true}, + {bytes, new RequestMessageBodyMatcher((byte[] b) => b.SequenceEqual(bytes)), true}, + + // binary no match --- + {bytes, new RequestMessageBodyMatcher((object o) => false), false}, + {bytes, new RequestMessageBodyMatcher((string s) => false), false}, + {bytes, new RequestMessageBodyMatcher((byte[] b) => false), false}, + {bytes, new RequestMessageBodyMatcher(), false }, + }; + } + } + } +} diff --git a/test/WireMock.Net.Tests/Serialization/MatcherModelMapperTests.cs b/test/WireMock.Net.Tests/Serialization/MatcherModelMapperTests.cs index 0a9c8393..a87b554f 100644 --- a/test/WireMock.Net.Tests/Serialization/MatcherModelMapperTests.cs +++ b/test/WireMock.Net.Tests/Serialization/MatcherModelMapperTests.cs @@ -1,276 +1,276 @@ -using System; -using FluentAssertions; -using NFluent; -using WireMock.Admin.Mappings; -using WireMock.Matchers; -using WireMock.Serialization; -using WireMock.Settings; -using Xunit; - -namespace WireMock.Net.Tests.Serialization -{ - public class MatcherModelMapperTests - { - private readonly WireMockServerSettings _settings = new WireMockServerSettings(); - - private readonly MatcherMapper _sut; - - public MatcherModelMapperTests() - { - _sut = new MatcherMapper(_settings); - } - - [Fact] - public void MatcherModelMapper_Map_CSharpCodeMatcher() - { - // Assign - var model = new MatcherModel - { - Name = "CSharpCodeMatcher", - Patterns = new[] { "return it == \"x\";" } - }; - var sut = new MatcherMapper(new WireMockServerSettings { AllowCSharpCodeMatcher = true }); - - // Act 1 - var matcher1 = (ICSharpCodeMatcher)sut.Map(model); - - // Assert 1 - matcher1.Should().NotBeNull(); +using System; +using FluentAssertions; +using NFluent; +using WireMock.Admin.Mappings; +using WireMock.Matchers; +using WireMock.Serialization; +using WireMock.Settings; +using Xunit; + +namespace WireMock.Net.Tests.Serialization +{ + public class MatcherModelMapperTests + { + private readonly WireMockServerSettings _settings = new WireMockServerSettings(); + + private readonly MatcherMapper _sut; + + public MatcherModelMapperTests() + { + _sut = new MatcherMapper(_settings); + } + + [Fact] + public void MatcherModelMapper_Map_CSharpCodeMatcher() + { + // Assign + var model = new MatcherModel + { + Name = "CSharpCodeMatcher", + Patterns = new[] { "return it == \"x\";" } + }; + var sut = new MatcherMapper(new WireMockServerSettings { AllowCSharpCodeMatcher = true }); + + // Act 1 + var matcher1 = (ICSharpCodeMatcher)sut.Map(model); + + // Assert 1 + matcher1.Should().NotBeNull(); matcher1.IsMatch("x").Should().Be(1.0d); // Act 2 - var matcher2 = (ICSharpCodeMatcher)sut.Map(model); - - // Assert 2 - matcher2.Should().NotBeNull(); - matcher2.IsMatch("x").Should().Be(1.0d); - } - - [Fact] - public void MatcherModelMapper_Map_CSharpCodeMatcher_NotAllowed_ThrowsException() - { - // Assign - var model = new MatcherModel - { - Name = "CSharpCodeMatcher", - Patterns = new[] { "x" } - }; - var sut = new MatcherMapper(new WireMockServerSettings { AllowCSharpCodeMatcher = false }); - - // Act - Action action = () => sut.Map(model); - - // Assert - action.Should().Throw(); - } - - [Fact] - public void MatcherModelMapper_Map_Null() - { - // Act - IMatcher matcher = _sut.Map((MatcherModel)null); - - // Assert - Check.That(matcher).IsNull(); - } - - [Fact] - public void MatcherModelMapper_Map_ExactMatcher_Pattern() - { - // Assign - var model = new MatcherModel - { - Name = "ExactMatcher", - Patterns = new[] { "x" } - }; - - // Act - var matcher = (ExactMatcher)_sut.Map(model); - - // Assert - matcher.GetPatterns().Should().ContainSingle("x"); - matcher.ThrowException.Should().BeFalse(); - } - - [Fact] - public void MatcherModelMapper_Map_ExactMatcher_Patterns() - { - // Assign - var model = new MatcherModel - { - Name = "ExactMatcher", - Patterns = new[] { "x", "y" } - }; - - // Act - var matcher = (ExactMatcher)_sut.Map(model); - - // Assert - Check.That(matcher.GetPatterns()).ContainsExactly("x", "y"); - } - - [Theory] - [InlineData(nameof(LinqMatcher))] - [InlineData(nameof(ExactMatcher))] - [InlineData(nameof(ExactObjectMatcher))] - [InlineData(nameof(RegexMatcher))] - [InlineData(nameof(JsonMatcher))] - [InlineData(nameof(JsonPathMatcher))] - [InlineData(nameof(JmesPathMatcher))] - [InlineData(nameof(XPathMatcher))] - [InlineData(nameof(WildcardMatcher))] - [InlineData(nameof(ContentTypeMatcher))] - [InlineData(nameof(SimMetricsMatcher))] - public void MatcherModelMapper_Map_ThrowExceptionWhenMatcherFails_True(string name) - { - // Assign - var settings = new WireMockServerSettings - { - ThrowExceptionWhenMatcherFails = true - }; - var sut = new MatcherMapper(settings); - var model = new MatcherModel - { - Name = name, - Patterns = new[] { "" } - }; - - // Act - var matcher = sut.Map(model); - - // Assert - matcher.ThrowException.Should().BeTrue(); - } - - [Fact] - public void MatcherModelMapper_Map_ExactObjectMatcher_ValidBase64StringPattern() - { - // Assign - var model = new MatcherModel - { - Name = "ExactObjectMatcher", - Patterns = new object[] { "c3RlZg==" } - }; - - // Act - var matcher = (ExactObjectMatcher)_sut.Map(model); - - // Assert - Check.That(matcher.ValueAsBytes).ContainsExactly(new byte[] { 115, 116, 101, 102 }); - } - - [Fact] - public void MatcherModelMapper_Map_ExactObjectMatcher_InvalidBase64StringPattern() - { - // Assign - var model = new MatcherModel - { - Name = "ExactObjectMatcher", - Patterns = new object[] { "_" } - }; - - // Act & Assert - Check.ThatCode(() => _sut.Map(model)).Throws(); - } - - [Fact] - public void MatcherModelMapper_Map_RegexMatcher() - { - // Assign - var model = new MatcherModel - { - Name = "RegexMatcher", - Patterns = new[] { "x", "y" }, - IgnoreCase = true - }; - - // Act - var matcher = (RegexMatcher)_sut.Map(model); - - // Assert - Check.That(matcher.GetPatterns()).ContainsExactly("x", "y"); - Check.That(matcher.IsMatch("X")).IsEqualTo(0.5d); - } - - [Fact] - public void MatcherModelMapper_Map_WildcardMatcher() - { - // Assign - var model = new MatcherModel - { - Name = "WildcardMatcher", - Patterns = new[] { "x", "y" }, - IgnoreCase = true - }; - - // Act - var matcher = (WildcardMatcher)_sut.Map(model); - - // Assert - Check.That(matcher.GetPatterns()).ContainsExactly("x", "y"); - Check.That(matcher.IsMatch("X")).IsEqualTo(0.5d); - } - - [Fact] - public void MatcherModelMapper_Map_SimMetricsMatcher() - { - // Assign - var model = new MatcherModel - { - Name = "SimMetricsMatcher", - Pattern = "x" - }; - - // Act - var matcher = (SimMetricsMatcher)_sut.Map(model); - - // Assert - Check.That(matcher.GetPatterns()).ContainsExactly("x"); - } - - [Fact] - public void MatcherModelMapper_Map_SimMetricsMatcher_BlockDistance() - { - // Assign - var model = new MatcherModel - { - Name = "SimMetricsMatcher.BlockDistance", - Pattern = "x" - }; - - // Act - var matcher = (SimMetricsMatcher)_sut.Map(model); - - // Assert - Check.That(matcher.GetPatterns()).ContainsExactly("x"); - } - - [Fact] - public void MatcherModelMapper_Map_SimMetricsMatcher_Throws1() - { - // Assign - var model = new MatcherModel - { - Name = "error", - Pattern = "x" - }; - - // Act - Check.ThatCode(() => _sut.Map(model)).Throws(); - } - - [Fact] - public void MatcherModelMapper_Map_SimMetricsMatcher_Throws2() - { - // Assign - var model = new MatcherModel - { - Name = "SimMetricsMatcher.error", - Pattern = "x" - }; - - // Act - Check.ThatCode(() => _sut.Map(model)).Throws(); - } - } + var matcher2 = (ICSharpCodeMatcher)sut.Map(model); + + // Assert 2 + matcher2.Should().NotBeNull(); + matcher2.IsMatch("x").Should().Be(1.0d); + } + + [Fact] + public void MatcherModelMapper_Map_CSharpCodeMatcher_NotAllowed_ThrowsException() + { + // Assign + var model = new MatcherModel + { + Name = "CSharpCodeMatcher", + Patterns = new[] { "x" } + }; + var sut = new MatcherMapper(new WireMockServerSettings { AllowCSharpCodeMatcher = false }); + + // Act + Action action = () => sut.Map(model); + + // Assert + action.Should().Throw(); + } + + [Fact] + public void MatcherModelMapper_Map_Null() + { + // Act + IMatcher matcher = _sut.Map((MatcherModel)null); + + // Assert + Check.That(matcher).IsNull(); + } + + [Fact] + public void MatcherModelMapper_Map_ExactMatcher_Pattern() + { + // Assign + var model = new MatcherModel + { + Name = "ExactMatcher", + Patterns = new[] { "x" } + }; + + // Act + var matcher = (ExactMatcher)_sut.Map(model); + + // Assert + matcher.GetPatterns().Should().ContainSingle("x"); + matcher.ThrowException.Should().BeFalse(); + } + + [Fact] + public void MatcherModelMapper_Map_ExactMatcher_Patterns() + { + // Assign + var model = new MatcherModel + { + Name = "ExactMatcher", + Patterns = new[] { "x", "y" } + }; + + // Act + var matcher = (ExactMatcher)_sut.Map(model); + + // Assert + Check.That(matcher.GetPatterns()).ContainsExactly("x", "y"); + } + + [Theory] + [InlineData(nameof(LinqMatcher))] + [InlineData(nameof(ExactMatcher))] + [InlineData(nameof(ExactObjectMatcher))] + [InlineData(nameof(RegexMatcher))] + [InlineData(nameof(JsonMatcher))] + [InlineData(nameof(JsonPathMatcher))] + [InlineData(nameof(JmesPathMatcher))] + [InlineData(nameof(XPathMatcher))] + [InlineData(nameof(WildcardMatcher))] + [InlineData(nameof(ContentTypeMatcher))] + [InlineData(nameof(SimMetricsMatcher))] + public void MatcherModelMapper_Map_ThrowExceptionWhenMatcherFails_True(string name) + { + // Assign + var settings = new WireMockServerSettings + { + ThrowExceptionWhenMatcherFails = true + }; + var sut = new MatcherMapper(settings); + var model = new MatcherModel + { + Name = name, + Patterns = new[] { "" } + }; + + // Act + var matcher = sut.Map(model); + + // Assert + matcher.ThrowException.Should().BeTrue(); + } + + [Fact] + public void MatcherModelMapper_Map_ExactObjectMatcher_ValidBase64StringPattern() + { + // Assign + var model = new MatcherModel + { + Name = "ExactObjectMatcher", + Patterns = new object[] { "c3RlZg==" } + }; + + // Act + var matcher = (ExactObjectMatcher)_sut.Map(model); + + // Assert + Check.That(matcher.ValueAsBytes).ContainsExactly(new byte[] { 115, 116, 101, 102 }); + } + + [Fact] + public void MatcherModelMapper_Map_ExactObjectMatcher_InvalidBase64StringPattern() + { + // Assign + var model = new MatcherModel + { + Name = "ExactObjectMatcher", + Patterns = new object[] { "_" } + }; + + // Act & Assert + Check.ThatCode(() => _sut.Map(model)).Throws(); + } + + [Fact] + public void MatcherModelMapper_Map_RegexMatcher() + { + // Assign + var model = new MatcherModel + { + Name = "RegexMatcher", + Patterns = new[] { "x", "y" }, + IgnoreCase = true + }; + + // Act + var matcher = (RegexMatcher)_sut.Map(model); + + // Assert + Check.That(matcher.GetPatterns()).ContainsExactly("x", "y"); + Check.That(matcher.IsMatch("X")).IsEqualTo(0.5d); + } + + [Fact] + public void MatcherModelMapper_Map_WildcardMatcher() + { + // Assign + var model = new MatcherModel + { + Name = "WildcardMatcher", + Patterns = new[] { "x", "y" }, + IgnoreCase = true + }; + + // Act + var matcher = (WildcardMatcher)_sut.Map(model); + + // Assert + Check.That(matcher.GetPatterns()).ContainsExactly("x", "y"); + Check.That(matcher.IsMatch("X")).IsEqualTo(0.5d); + } + + [Fact] + public void MatcherModelMapper_Map_SimMetricsMatcher() + { + // Assign + var model = new MatcherModel + { + Name = "SimMetricsMatcher", + Pattern = "x" + }; + + // Act + var matcher = (SimMetricsMatcher)_sut.Map(model); + + // Assert + Check.That(matcher.GetPatterns()).ContainsExactly("x"); + } + + [Fact] + public void MatcherModelMapper_Map_SimMetricsMatcher_BlockDistance() + { + // Assign + var model = new MatcherModel + { + Name = "SimMetricsMatcher.BlockDistance", + Pattern = "x" + }; + + // Act + var matcher = (SimMetricsMatcher)_sut.Map(model); + + // Assert + Check.That(matcher.GetPatterns()).ContainsExactly("x"); + } + + [Fact] + public void MatcherModelMapper_Map_SimMetricsMatcher_Throws1() + { + // Assign + var model = new MatcherModel + { + Name = "error", + Pattern = "x" + }; + + // Act + Check.ThatCode(() => _sut.Map(model)).Throws(); + } + + [Fact] + public void MatcherModelMapper_Map_SimMetricsMatcher_Throws2() + { + // Assign + var model = new MatcherModel + { + Name = "SimMetricsMatcher.error", + Pattern = "x" + }; + + // Act + Check.ThatCode(() => _sut.Map(model)).Throws(); + } + } } \ No newline at end of file