diff --git a/src/WireMock.Net/Owin/MappingMatcher.cs b/src/WireMock.Net/Owin/MappingMatcher.cs
index 230fe4d4..bc3342a8 100644
--- a/src/WireMock.Net/Owin/MappingMatcher.cs
+++ b/src/WireMock.Net/Owin/MappingMatcher.cs
@@ -35,11 +35,7 @@ internal class MappingMatcher : IMappingMatcher
{
var nextState = GetNextState(mapping);
- var mappingMatcherResult = new MappingMatcherResult
- {
- Mapping = mapping,
- RequestMatchResult = mapping.GetRequestMatchResult(request, nextState)
- };
+ var mappingMatcherResult = new MappingMatcherResult(mapping, mapping.GetRequestMatchResult(request, nextState));
var exceptions = mappingMatcherResult.RequestMatchResult.MatchDetails
.Where(md => md.Exception != null)
@@ -66,7 +62,10 @@ internal class MappingMatcher : IMappingMatcher
var partialMappings = possibleMappings
.Where(pm => (pm.Mapping.IsAdminInterface && pm.RequestMatchResult.IsPerfectMatch) || !pm.Mapping.IsAdminInterface)
- .OrderBy(m => m.RequestMatchResult).ThenBy(m => m.Mapping.Priority).ThenByDescending(m => m.Mapping.UpdatedAt)
+ .OrderBy(m => m.RequestMatchResult)
+ .ThenBy(m => m.RequestMatchResult.TotalNumber)
+ .ThenBy(m => m.Mapping.Priority)
+ .ThenByDescending(m => m.Mapping.UpdatedAt)
.ToList();
var partialMatch = partialMappings.FirstOrDefault(pm => pm.RequestMatchResult.AverageTotalScore > 0.0);
diff --git a/src/WireMock.Net/Owin/MappingMatcherResult.cs b/src/WireMock.Net/Owin/MappingMatcherResult.cs
index 34448303..848a69bb 100644
--- a/src/WireMock.Net/Owin/MappingMatcherResult.cs
+++ b/src/WireMock.Net/Owin/MappingMatcherResult.cs
@@ -1,10 +1,17 @@
+using Stef.Validation;
using WireMock.Matchers.Request;
namespace WireMock.Owin;
internal class MappingMatcherResult
{
- public IMapping Mapping { get; set; }
+ public IMapping Mapping { get; }
- public IRequestMatchResult RequestMatchResult { get; set; }
+ public IRequestMatchResult RequestMatchResult { get; }
+
+ public MappingMatcherResult(IMapping mapping, IRequestMatchResult requestMatchResult)
+ {
+ Mapping = Guard.NotNull(mapping);
+ RequestMatchResult = Guard.NotNull(requestMatchResult);
+ }
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Server/IRespondWithAProvider.cs b/src/WireMock.Net/Server/IRespondWithAProvider.cs
index b62840b5..ea3bec77 100644
--- a/src/WireMock.Net/Server/IRespondWithAProvider.cs
+++ b/src/WireMock.Net/Server/IRespondWithAProvider.cs
@@ -61,7 +61,7 @@ public interface IRespondWithAProvider
///
/// Define the priority for this mapping.
///
- /// The priority.
+ /// The priority. (A lower value means a higher priority.)
/// The .
IRespondWithAProvider AtPriority(int priority);
diff --git a/test/WireMock.Net.Tests/Owin/WireMockMiddlewareTests.cs b/test/WireMock.Net.Tests/Owin/WireMockMiddlewareTests.cs
index 7bd2913f..b7e85b89 100644
--- a/test/WireMock.Net.Tests/Owin/WireMockMiddlewareTests.cs
+++ b/test/WireMock.Net.Tests/Owin/WireMockMiddlewareTests.cs
@@ -16,6 +16,7 @@ using WireMock.Admin.Requests;
using WireMock.Settings;
using FluentAssertions;
using WireMock.Handlers;
+using WireMock.Matchers.Request;
using WireMock.ResponseBuilders;
using WireMock.RequestBuilders;
#if NET452
@@ -43,6 +44,7 @@ public class WireMockMiddlewareTests
private readonly Mock _responseMapperMock;
private readonly Mock _matcherMock;
private readonly Mock _mappingMock;
+ private readonly Mock _requestMatchResultMock;
private readonly Mock _contextMock;
private readonly WireMockMiddleware _sut;
@@ -72,12 +74,16 @@ public class WireMockMiddlewareTests
_matcherMock = new Mock();
_matcherMock.SetupAllProperties();
- _matcherMock.Setup(m => m.FindBestMatch(It.IsAny())).Returns((new MappingMatcherResult(), new MappingMatcherResult()));
+ // _matcherMock.Setup(m => m.FindBestMatch(It.IsAny())).Returns((new MappingMatcherResult(), new MappingMatcherResult()));
_contextMock = new Mock();
_mappingMock = new Mock();
+ _requestMatchResultMock = new Mock();
+ _requestMatchResultMock.Setup(r => r.TotalNumber).Returns(1);
+ _requestMatchResultMock.Setup(r => r.MatchDetails).Returns(new List());
+
_sut = new WireMockMiddleware(
null,
_optionsMock.Object,
@@ -133,7 +139,7 @@ public class WireMockMiddlewareTests
_optionsMock.SetupGet(o => o.AuthenticationMatcher).Returns(new ExactMatcher());
_mappingMock.SetupGet(m => m.IsAdminInterface).Returns(true);
- var result = new MappingMatcherResult { Mapping = _mappingMock.Object };
+ var result = new MappingMatcherResult(_mappingMock.Object, _requestMatchResultMock.Object);
_matcherMock.Setup(m => m.FindBestMatch(It.IsAny())).Returns((result, result));
// Act
@@ -156,7 +162,7 @@ public class WireMockMiddlewareTests
_optionsMock.SetupGet(o => o.AuthenticationMatcher).Returns(new ExactMatcher());
_mappingMock.SetupGet(m => m.IsAdminInterface).Returns(true);
- var result = new MappingMatcherResult { Mapping = _mappingMock.Object };
+ var result = new MappingMatcherResult(_mappingMock.Object, _requestMatchResultMock.Object);
_matcherMock.Setup(m => m.FindBestMatch(It.IsAny())).Returns((result, result));
// Act
@@ -216,7 +222,7 @@ public class WireMockMiddlewareTests
var requestBuilder = Request.Create().UsingAnyMethod();
_mappingMock.SetupGet(m => m.RequestMatcher).Returns(requestBuilder);
- var result = new MappingMatcherResult { Mapping = _mappingMock.Object };
+ var result = new MappingMatcherResult(_mappingMock.Object, _requestMatchResultMock.Object);
_matcherMock.Setup(m => m.FindBestMatch(It.IsAny())).Returns((result, result));
// Act
@@ -270,7 +276,7 @@ public class WireMockMiddlewareTests
var requestBuilder = Request.Create().UsingAnyMethod();
_mappingMock.SetupGet(m => m.RequestMatcher).Returns(requestBuilder);
- var result = new MappingMatcherResult { Mapping = _mappingMock.Object };
+ var result = new MappingMatcherResult (_mappingMock.Object, _requestMatchResultMock.Object);
_matcherMock.Setup(m => m.FindBestMatch(It.IsAny())).Returns((result, result));
// Act
diff --git a/test/WireMock.Net.Tests/RequestMatchers/RequestMessageBodyMatcherTests.cs b/test/WireMock.Net.Tests/RequestMatchers/RequestMessageBodyMatcherTests.cs
index 26812d12..7fa47186 100644
--- a/test/WireMock.Net.Tests/RequestMatchers/RequestMessageBodyMatcherTests.cs
+++ b/test/WireMock.Net.Tests/RequestMatchers/RequestMessageBodyMatcherTests.cs
@@ -300,6 +300,31 @@ public class RequestMessageBodyMatcherTests
Check.That(score).IsEqualTo(1.0d);
}
+ [Fact]
+ public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsJson_JmesPathMatchers()
+ {
+ // Arrange
+ var body = new BodyData
+ {
+ BodyAsJson = new { requestId = "1", value = "A" },
+ DetectedBodyType = BodyType.Json
+ };
+
+ var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body);
+
+ var jmesMatcher1 = new JmesPathMatcher("requestId == '1'");
+ var jmesMatcher2 = new JmesPathMatcher("value == 'A'");
+
+ var bodyMatcher = new RequestMessageBodyMatcher(MatchOperator.And, jmesMatcher1, jmesMatcher2);
+
+ // Act
+ var result = new RequestMatchResult();
+ double score = bodyMatcher.GetMatchingScore(requestMessage, result);
+
+ // Assert
+ score.Should().Be(MatchScores.Perfect);
+ }
+
[Theory]
[InlineData(null, 0.0)]
[InlineData(new byte[0], 0.0)]
diff --git a/test/WireMock.Net.Tests/Util/StringUtilsTests.cs b/test/WireMock.Net.Tests/Util/StringUtilsTests.cs
index 4a9ca6c9..657dd369 100644
--- a/test/WireMock.Net.Tests/Util/StringUtilsTests.cs
+++ b/test/WireMock.Net.Tests/Util/StringUtilsTests.cs
@@ -1,4 +1,5 @@
using FluentAssertions;
+using WireMock.Matchers;
using WireMock.Util;
using Xunit;
@@ -6,13 +7,39 @@ namespace WireMock.Net.Tests.Util;
public class StringUtilsTests
{
+ [Theory]
+ [InlineData("And", MatchOperator.And)]
+ [InlineData("Or", MatchOperator.Or)]
+ public void ParseMatchOperator_ShouldReturnCorrectEnumValue_WhenValidStringIsProvided(string value, MatchOperator expected)
+ {
+ // Arrange & Act
+ var result = StringUtils.ParseMatchOperator(value);
+
+ // Assert
+ result.Should().Be(expected);
+ }
+
+ [Theory]
+ [InlineData(null, MatchOperator.Or)]
+ [InlineData("", MatchOperator.Or)]
+ [InlineData("and", MatchOperator.Or)]
+ [InlineData("InvalidValue", MatchOperator.Or)]
+ public void ParseMatchOperator_ShouldReturnDefaultEnumValue_WhenInvalidOrNullStringIsProvided(string? value, MatchOperator expected)
+ {
+ // Arrange & Act
+ var result = StringUtils.ParseMatchOperator(value);
+
+ // Assert
+ result.Should().Be(expected);
+ }
+
[Theory]
[InlineData("'s")]
[InlineData("\"s")]
public void StringUtils_TryParseQuotedString_With_UnexpectedUnclosedString_Returns_False(string input)
{
// Act
- bool valid = StringUtils.TryParseQuotedString(input, out var result, out var quote);
+ var valid = StringUtils.TryParseQuotedString(input, out _, out _);
// Assert
valid.Should().BeFalse();
@@ -25,7 +52,7 @@ public class StringUtilsTests
public void StringUtils_TryParseQuotedString_With_InvalidStringLength_Returns_False(string input)
{
// Act
- bool valid = StringUtils.TryParseQuotedString(input, out var result, out var quote);
+ var valid = StringUtils.TryParseQuotedString(input, out _, out _);
// Assert
valid.Should().BeFalse();
@@ -37,7 +64,7 @@ public class StringUtilsTests
public void StringUtils_TryParseQuotedString_With_InvalidStringQuoteCharacter_Returns_False(string input)
{
// Act
- bool valid = StringUtils.TryParseQuotedString(input, out var result, out var quote);
+ var valid = StringUtils.TryParseQuotedString(input, out _, out _);
// Assert
valid.Should().BeFalse();
@@ -47,10 +74,10 @@ public class StringUtilsTests
public void StringUtils_TryParseQuotedString_With_UnexpectedUnrecognizedEscapeSequence_Returns_False()
{
// Arrange
- string input = new string(new[] { '"', '\\', 'u', '?', '"' });
+ var input = new string(new[] { '"', '\\', 'u', '?', '"' });
// Act
- bool valid = StringUtils.TryParseQuotedString(input, out var result, out var quote);
+ var valid = StringUtils.TryParseQuotedString(input, out _, out _);
// Assert
valid.Should().BeFalse();
@@ -64,7 +91,7 @@ public class StringUtilsTests
public void StringUtils_TryParseQuotedString_SingleQuotedString(string input, string expectedResult)
{
// Act
- bool valid = StringUtils.TryParseQuotedString(input, out var result, out var quote);
+ var valid = StringUtils.TryParseQuotedString(input, out var result, out var quote);
// Assert
valid.Should().BeTrue();
@@ -93,7 +120,7 @@ public class StringUtilsTests
public void StringUtils_TryParseQuotedString_DoubleQuotedString(string input, string expectedResult)
{
// Act
- bool valid = StringUtils.TryParseQuotedString(input, out var result, out var quote);
+ var valid = StringUtils.TryParseQuotedString(input, out var result, out var quote);
// Assert
valid.Should().BeTrue();
diff --git a/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj b/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj
index f6a3fb59..3fa60e0c 100644
--- a/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj
+++ b/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj
@@ -3,6 +3,8 @@
Stef Heyenrath
net452;net461;netcoreapp3.1;net6.0;net7.0
+ 11
+ enable
false
full
WireMock.Net.Tests
diff --git a/test/WireMock.Net.Tests/WireMockServerTests.WithBody.cs b/test/WireMock.Net.Tests/WireMockServerTests.WithBody.cs
index a891dfd3..cc90bef7 100644
--- a/test/WireMock.Net.Tests/WireMockServerTests.WithBody.cs
+++ b/test/WireMock.Net.Tests/WireMockServerTests.WithBody.cs
@@ -1,9 +1,8 @@
#if !NET452
-//using System;
+using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
-//using System.Net.Http.Json;
using System.Threading.Tasks;
using FluentAssertions;
using WireMock.Matchers;
@@ -21,6 +20,103 @@ public partial class WireMockServerTests
public string? Hi { get; set; }
}
+ [Fact]
+ public async Task WireMockServer_WithBodyAsJson_Using_PostAsJsonAsync_And_MultipleJmesPathMatchers_ShouldMatch()
+ {
+ // Arrange
+ var server = WireMockServer.Start();
+ server.Given(
+ Request.Create()
+ .WithPath("/a")
+ .WithBody(
+ new IMatcher[]
+ {
+ new JmesPathMatcher("requestId == '1'"),
+ new JmesPathMatcher("value == 'A'")
+ },
+ MatchOperator.And
+ )
+ .UsingPost()
+ )
+ .RespondWith(Response.Create().WithStatusCode(HttpStatusCode.OK));
+
+ server.Given(
+ Request.Create()
+ .WithPath("/a")
+ .WithBody(
+ new IMatcher[]
+ {
+ new JmesPathMatcher("requestId == '2'"),
+ new JmesPathMatcher("value == 'A'")
+ },
+ MatchOperator.And
+ )
+ .UsingPost()
+ )
+ .RespondWith(Response.Create().WithStatusCode(HttpStatusCode.Moved));
+
+ // Act
+ var requestUri = new Uri($"http://localhost:{server.Port}/a");
+
+ var json = new { requestId = "1", value = "A" };
+ var response = await server.CreateClient().PostAsJsonAsync(requestUri, json).ConfigureAwait(false);
+
+ // Assert
+ response.StatusCode.Should().Be(HttpStatusCode.OK);
+
+ server.Stop();
+ }
+
+ [Fact]
+ public async Task WireMockServer_WithBodyAsJson_Using_PostAsJsonAsync_And_MultipleJmesPathMatchers_ShouldMatch_BestMatching()
+ {
+ // Arrange
+ var server = WireMockServer.Start();
+ server.Given(
+ Request.Create()
+ .WithPath("/a")
+ .WithBody(
+ new IMatcher[]
+ {
+ new JmesPathMatcher("extra == 'X'"),
+ new JmesPathMatcher("requestId == '1'"),
+ new JmesPathMatcher("value == 'A'")
+ },
+ MatchOperator.And
+ )
+ .UsingPost()
+ )
+ .AtPriority(1) // Higher priority
+ .RespondWith(Response.Create().WithStatusCode(HttpStatusCode.OK));
+
+ server.Given(
+ Request.Create()
+ .WithPath("/a")
+ .WithBody(
+ new IMatcher[]
+ {
+ new JmesPathMatcher("requestId == '1'"),
+ new JmesPathMatcher("value == 'A'")
+ },
+ MatchOperator.And
+ )
+ .UsingPost()
+ )
+ .AtPriority(2)
+ .RespondWith(Response.Create().WithStatusCode(HttpStatusCode.Moved));
+
+ // Act
+ var requestUri = new Uri($"http://localhost:{server.Port}/a");
+
+ var json = new { extra = "X", requestId = "1", value = "A" };
+ var response = await server.CreateClient().PostAsJsonAsync(requestUri, json).ConfigureAwait(false);
+
+ // Assert
+ response.StatusCode.Should().Be(HttpStatusCode.OK);
+
+ server.Stop();
+ }
+
[Fact]
public async Task WireMockServer_WithBodyAsJson_Using_PostAsJsonAsync_And_WildcardMatcher_ShouldMatch()
{