How to make Request mapping match only when it is a perfect match? #309

Closed
opened 2025-12-29 15:20:20 +01:00 by adam · 4 comments
Owner

Originally created by @tomatualus on GitHub (Oct 20, 2020).

Hello.

Lets say i have two request mappings. The XPathMatchers are simplified.

Request 1 has body matchers XPathMatcher for Value1 = 1 AND XPathMatcher for Value2 = 2.
Request 2 has a body matcher XPathMatcher for Value1 = 1.

How do i return the Request 1's response, when its matchers are a perfect fit, but return Request 2, when Value2 != 2?

Thanks in advance.

Originally created by @tomatualus on GitHub (Oct 20, 2020). Hello. Lets say i have two request mappings. The `XPathMatchers` are simplified. Request 1 has body **matchers** `XPathMatcher` for Value1 = 1 **AND** `XPathMatcher` for Value2 = 2. Request 2 has a body **matcher** `XPathMatcher` for Value1 = 1. How do i return the Request 1's response, when its matchers are a perfect fit, but return Request 2, when Value2 != 2? Thanks in advance.
adam added the question label 2025-12-29 15:20:20 +01:00
adam closed this issue 2025-12-29 15:20:21 +01:00
Author
Owner

@StefH commented on GitHub (Oct 20, 2020):

Hello @tomatualus,

  1. The current logic from WireMock.Net is that in case two mappings are a perfect fit, the one with the most matches is preferred.

  2. Your second scenario return Request 2, when Value2 != 2 , I'm not completely sure that can be done right now. But I would would expect it to work correct, that is : return Request 2 because Request 1 does only only match for 50%.

See also https://github.com/WireMock-Net/WireMock.Net/blob/master/test/WireMock.Net.Tests/Owin/MappingMatcherTests.cs#L145

@StefH commented on GitHub (Oct 20, 2020): Hello @tomatualus, 1. The current logic from WireMock.Net is that in case two mappings are a perfect fit, the one with the most matches is preferred. 2. Your second scenario _return Request 2, when Value2 != 2_ , I'm not completely sure that can be done right now. But I would would expect it to work correct, that is : return Request 2 because Request 1 does only only match for 50%. See also https://github.com/WireMock-Net/WireMock.Net/blob/master/test/WireMock.Net.Tests/Owin/MappingMatcherTests.cs#L145
Author
Owner

@tomatualus commented on GitHub (Oct 21, 2020):

Thanks for the reply @StefH

I will post my class setup down below. You can see that it doesn't work as expected, even though online XPath tools show that one of XPathMatchers should fail. Both of them return `Failed but no delay
Also the setup below has this scenario -

Request 1 has body matchers XPathMatcher for FirstForename = Failed AND XPathMatcher for Surname = Delay.
Request 2 has body matchers XPathMatcher for FirstForename = Failed AND XPathMatcher for Surname != Delay.

    private static WireMockServer stub;
    private static string baseUrl;

    [ClassInitialize]
    public static void PrepareClass(TestContext context)
    {
        if (context is null) { throw new ArgumentNullException(nameof(context)); }

        var config = new ConfigReader();
        var port = 5069;
        baseUrl = "http://localhost:" + port;

        stub = WireMockServer.Start(new WireMockServerSettings
        {
            Urls = new[] { "http://+:" + port },
            ReadStaticMappings = true,
            FileSystemHandler = new CustomFileSystemHandler(config.WireMockMappingPath),
            WatchStaticMappings = true,
            WatchStaticMappingsInSubdirectories = true,
        });
    }

    [ClassCleanup]
    public static void TearDown()
    {
        stub.Stop();
    }

    [TestMethod]
    public void Test()

    {

        stub.Given(
            Request.Create()
                .WithPath("/test1")
                .WithBody(new IMatcher[]
                {
                    new XPathMatcher("string(//*[name()='IndividualName']/*[name()='FirstForename']) = 'Failed'"),
                    new XPathMatcher("string(//*[name()='IndividualName']/*[name()='Surname']) != 'Delay'"),
                }))
            .RespondWith(
                Response.Create()
                .WithStatusCode(200)
                .WithBody("Failed but no delay")
            );

        stub.Given(
            Request.Create()
                .WithPath("/test1")
                .UsingPost()
                .WithBody(new IMatcher[]
                {
                    new XPathMatcher("string(//*[name()='IndividualName']/*[name()='FirstForename']) = 'Failed'"),
                    new XPathMatcher("string(//*[name()='IndividualName']/*[name()='Surname']) = 'Delay'"),
                }))
            .RespondWith(
                Response.Create()
                .WithStatusCode(200)
                .WithBody("Failed and delay")
            );

        var client = new RestSharp.RestClient($"{baseUrl}/test1");
        var request1 = new RestRequest(Method.POST);
        request1.AddParameter(
            "text/xml",
            "<IndividualName><FirstForename>Failed</FirstForename><Surname>Delay</Surname></IndividualName>",
            ParameterType.RequestBody);

        var request2 = new RestRequest(Method.POST);
        request2.AddParameter(
            "text/xml",
            "<IndividualName><FirstForename>Failed</FirstForename><Surname>NotDelay</Surname></IndividualName>",
            ParameterType.RequestBody);

        var response1 = client.Execute(request1).Content;
        var response2 = client.Execute(request2).Content;
    }

EDIT:

Interestingly enough, if i comment out

    // new XPathMatcher("string(//*[name()='IndividualName']/*[name()='FirstForename']) = 'Failed'"),

In both of the matchers, it correctly returns Failed and delay and Failed but no delay

@tomatualus commented on GitHub (Oct 21, 2020): Thanks for the reply @StefH I will post my class setup down below. You can see that it doesn't work as expected, even though online XPath tools show that one of XPathMatchers should fail. Both of them return `Failed but no delay Also the setup below has this scenario - Request 1 has body matchers XPathMatcher for FirstForename = Failed AND XPathMatcher for Surname = Delay. Request 2 has body matchers XPathMatcher for FirstForename = Failed AND XPathMatcher for Surname != Delay. ``` c# private static WireMockServer stub; private static string baseUrl; [ClassInitialize] public static void PrepareClass(TestContext context) { if (context is null) { throw new ArgumentNullException(nameof(context)); } var config = new ConfigReader(); var port = 5069; baseUrl = "http://localhost:" + port; stub = WireMockServer.Start(new WireMockServerSettings { Urls = new[] { "http://+:" + port }, ReadStaticMappings = true, FileSystemHandler = new CustomFileSystemHandler(config.WireMockMappingPath), WatchStaticMappings = true, WatchStaticMappingsInSubdirectories = true, }); } [ClassCleanup] public static void TearDown() { stub.Stop(); } [TestMethod] public void Test() { stub.Given( Request.Create() .WithPath("/test1") .WithBody(new IMatcher[] { new XPathMatcher("string(//*[name()='IndividualName']/*[name()='FirstForename']) = 'Failed'"), new XPathMatcher("string(//*[name()='IndividualName']/*[name()='Surname']) != 'Delay'"), })) .RespondWith( Response.Create() .WithStatusCode(200) .WithBody("Failed but no delay") ); stub.Given( Request.Create() .WithPath("/test1") .UsingPost() .WithBody(new IMatcher[] { new XPathMatcher("string(//*[name()='IndividualName']/*[name()='FirstForename']) = 'Failed'"), new XPathMatcher("string(//*[name()='IndividualName']/*[name()='Surname']) = 'Delay'"), })) .RespondWith( Response.Create() .WithStatusCode(200) .WithBody("Failed and delay") ); var client = new RestSharp.RestClient($"{baseUrl}/test1"); var request1 = new RestRequest(Method.POST); request1.AddParameter( "text/xml", "<IndividualName><FirstForename>Failed</FirstForename><Surname>Delay</Surname></IndividualName>", ParameterType.RequestBody); var request2 = new RestRequest(Method.POST); request2.AddParameter( "text/xml", "<IndividualName><FirstForename>Failed</FirstForename><Surname>NotDelay</Surname></IndividualName>", ParameterType.RequestBody); var response1 = client.Execute(request1).Content; var response2 = client.Execute(request2).Content; } ``` EDIT: Interestingly enough, if i comment out ``` c# // new XPathMatcher("string(//*[name()='IndividualName']/*[name()='FirstForename']) = 'Failed'"), ``` In both of the matchers, it correctly returns `Failed and delay` and `Failed but no delay`
Author
Owner

@tomatualus commented on GitHub (Oct 21, 2020):

Just discovered the fix......

It seems like i can pass many strings into XPathMatcher.. So when consolidated both XPathMatchers into one, it now works.

But the question remains - why does the upper test not work?

@tomatualus commented on GitHub (Oct 21, 2020): Just discovered the fix...... It seems like i can pass many strings into `XPathMatcher`.. So when consolidated both XPathMatchers into one, it now works. But the question remains - why does the upper test not work?
Author
Owner

@StefH commented on GitHub (Oct 21, 2020):

Maybe you need to use not instead of != for strings?

https://stackoverflow.com/questions/3418470/using-not-in-xpath

@StefH commented on GitHub (Oct 21, 2020): Maybe you need to use `not` instead of `!=` for strings? https://stackoverflow.com/questions/3418470/using-not-in-xpath
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/WireMock.Net-wiremock#309