xmlxpathsoapwiremockservice-virtualization

Evaluate an expression that returns a boolean value in Wiremock - Request matching criteria


Trying to use Wiremock as a tool for virtualizing SOAP services.

The request mapping criteria looks something like below:-

Mapping Criteria:

   {
      "request":{
        "method":"POST",
        "urlPattern":"/myServices/mycontent.asgx",
        "headers":{
          "SOAPAction":{
            "contains":"#SearchMyContent"
          }
        },
        "bodyPatterns":[{
          **"matchesXPath":"//data:MyContentItemCode[contains(text(), 'SD_12345')] and //MyContentItemCode[contains(text(), 'SD_22222')]",**
          "xPathNamespaces":{
            "SOAP-ENV": "http://schemas.xmlsoap.org/soap/envelope/",
            "data":"http://www.ins.com/insi/1.0/insi-data",
            "msg":"http://www.ins.com/insi/1.0/insi-messaging",
            "nc":"http://www.ins.com/insi/1.0/insi-non-compliant",
            "soapenv":"http://schemas.xmlsoap.org/soap/envelope/",
            "srvc":"http://www.ins.com/insi/1.0/insi-services"
        }
        }]
      },
      "response":{
        "status":200,
        "headers":{
          "Content-Type":"text/xml;charset=utf-8"
        },
        "body":"encoded_XML_body"
      }
    } 

For security reasons, I cannot post the entire SOAP service request here but below is a small snippet from the SOAP service that has to be matched with the xpath in the mapping criteria

<srvc:MyContentItemCodeList>
    <data:MyContentItemCode>SD_12345</data:MyContentItemCode>
    <data:MyContentItemCode>SD_22222</data:MyContentItemCode>
</srvc:MyContentItemCodeList>

As you can see I am trying to match both the "data:MyContentItemCode" tags in my mapping criteria. However, wiremock doesn't recognize/support this. It could be because the xpath returns a boolean value. My questions is - Is there a way to match on boolean values in Wiremock.

I did not find an example in Wiremock documentation here:- http://wiremock.org/docs/request-matching/

When I post the mappings to the wiremock server, it does get posted successfully but when I try to hit the wiremock server I do not get back my virtualized response(i.e. the request matching isn't considered)

Any help/ pointers on this would be appreciated.


Solution

  • The issue you're facing is that you need to return an element/tag to the matcher. This can be done by using the root tag. In this example I used the soap envelope tag your example hinted to existing.

    The mechanism to only return the root element is by counting the number of elements matching your criteria. If both are true, then the root element is also returned. The below example does just that.

    mapping.json

       {
          "request":{
            "method":"POST",
            "urlPattern":"/dtag",
            "bodyPatterns":[{
              "matchesXPath":"/SOAP-ENV:Envelope[count(//data:MyContentItemCode[contains(text(), 'SD_12345')])=1 and count(//data:MyContentItemCode[contains(text(), 'SD_22222')] )=1]",
              "xPathNamespaces":{
                "SOAP-ENV": "http://schemas.xmlsoap.org/soap/envelope/",
                "data":"http://www.ins.com/insi/1.0/insi-data",
                "srvc":"http://www.ins.com/insi/1.0/insi-services"
            }       
    
            }]
          },
          "response":{
            "status":200,
            "headers":{
              "Content-Type":"text/xml;charset=utf-8"
            },
            "body":"encoded_XML_body"
          }
        } 
    

    The below XML is sent via POST request to the below URL. As WireMock is quite picky about the namespaces, please ensure that you have the right namespaces associated to the tags as they appear in your request.

    Request to http://localhost/dtag

    <?xml version="1.0"?>
    
    <soap:Envelope
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding"
    xmlns:data="http://www.ins.com/insi/1.0/insi-data"
    xmlns:srvc="http://www.ins.com/insi/1.0/insi-services">
        <srvc:MyContentItemCodeList >
        <data:MyContentItemCode>SD_12345</data:MyContentItemCode>
        <data:MyContentItemCode>SD_22222</data:MyContentItemCode>
        </srvc:MyContentItemCodeList>
    </soap:Envelope>