The SOAP vs. REST debate might have ended with REST as the clear winner in adoption for the most recent years, especially when we're talking about public APIs. However, SOAP APIs are still available and being used, especially in maintaining support for legacy systems, or in specific industries, such as financial and telecommunication services. Even big tech companies still have SOAP APIs available, such as PayPal, Flickr, and Salesforce.
Runscope supports testing any HTTP request, which includes making SOAP requests. In this tutorial, we're going to walk through how to test a SOAP API that returns geolocation information based on an IP address and validate its response using assertions and post-response scripts.
Testing a SOAP API Endpoint
Here's what a request to our IP2Geo SOAP API looks like:
POST /ip2geo/ip2geo.asmx HTTP/1.1 Host: ws.cdyne.com Content-Type: text/xml; charset=utf-8 Content-Length: length SOAPAction: "http://ws.cdyne.com/ResolveIP" <?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <ResolveIP xmlns="http://ws.cdyne.com/"> <ipAddress>string</ipAddress> <licenseKey>string</licenseKey> </ResolveIP> </soap:Body> </soap:Envelope>
We're using SOAP 1.1 here, but the API also supports SOAP 1.2, and you can test both versions using Runscope.
For this example, I'm going to be using my IP address, which will return an address from Chicago, in the US. You can use your own public IP address in the following steps if you want, and you can find it by searching for "what's my IP" on Google, or typing the following command in your terminal:
The first thing we need to do is create a new test in the Runscope interface, and set the following parameters:
- Method: POST
- URL: https://ws.cdyne.com/ip2geo/ip2geo.asmx
- SOAPAction: "http://ws.cdyne.com/ResolveIP"
- Content-Length: length
- Content-Type: text/xml; charset=utf-8
Then, we need to add our request's envelope body by clicking on "+ Add Body", and set two parameters:
- ipAddress - Change it to your IP address. In this case, I'm using my IP which is "220.127.116.11".
- licenseKey - Set this to 0 since we're just testing the API.
<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <ResolveIP xmlns="http://ws.cdyne.com/"> <ipAddress>18.104.22.168</ipAddress> <licenseKey>0</licenseKey> </ResolveIP> </soap:Body> </soap:Envelope>
Now, we just click on "Save & Run" at the top to run our request.
We can see the results by clicking on the first item on the left-hand side, under "Recent Test Runs". Our SOAP API is going to return an XML object, and it should look similar to this:
<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <soap:Body> <ResolveIPResponse xmlns="http://ws.cdyne.com/"> <ResolveIPResult> <City>Chicago</City> <StateProvince>IL</StateProvince> <Country>United States</Country> <Organization /> <Latitude>41.97279</Latitude> <Longitude>-87.6616</Longitude> <AreaCode>773</AreaCode> <TimeZone /> <HasDaylightSavings>false</HasDaylightSavings> <Certainty>90</Certainty> <RegionName /> <CountryCode>US</CountryCode> </ResolveIPResult> </ResolveIPResponse> </soap:Body> </soap:Envelope>
Note: if you get an invalid response, make sure that you're using a valid public IP address in your request.
Validating Response Data with Assertions
Ok, so we know that our test and our SOAP API is working. For the next step, we want to make sure that our response is returning the correct data. There are two ways we can create assertions in the Runscope interface:
Built-in XML Assertions
The first way we can do that is by clicking on the "Assertion" tab in our test editor:
We already have a default assertion set up that we expect our test to return a 200 status code. Now, let's add another assertion that will check that the `City` element is equal to the city our IP address resolves to.
To do that, we first click on "+ Add Assertion". Then, we set our "Source" to "XML Body", and under "Property", we're going to set it to: "//*[local-name()='City']/text()"
That is an XPath expression we're using to search for all elements named "City", and then extracting their text value. You can learn more about XPath expression and play around with them by using this XPath Tester/Evaluator tool.
We also need to set the Comparison field to "equals", and the Target Value to the city your IP address resolves to. In my case, I'll just set it to "Chicago":
Now, we can rerun our test and see if it's still passing by clicking on "Save & Run" at the top, and then heading over to our test result:
Another way for us to test that our response data is correct is by using the Post-response Scripts feature. We can use one of the included libraries, marknote XML Parser, to work with the XML response and retrieve the elements we want to test.
So, if we wanted to do a similar assertion as we did in the last step, we can go to the Post-response Script tab in our test step and add the following script:
var str = response.body; var parser = new marknote.Parser(); var xml = parser.parse(str); var body = xml.getRootElement(); var resp = body.getChildElement("ResolveIPResponse"); var result = resp.getChildElement("ResolveIPResult"); var city = result.getChildElement("City"); assert(city.getText() === "Chicago", "Windy City is correct!");
And we can see our script output and success message in the test result:
If you run into any issues with the Marknote parser, you can also convert your XML to JSON to more easily access properties. For example, our post-response script would be:
var jsonResponse = JSON.parse(xmltojson(response.body)); var city = jsonResponse[‘ResolveIPResponse’][‘ResolveIPResult’][‘City’]; assert(city === "Chicago", "Windy City is correct!");
Using scripts can be useful if you plan to do something more complex with the data you get back from your SOAP API. You can also combine scripts with snippets to avoid repeating that boilerplate XML parsing code in our example script, and reuse assertions across multiple tests.
Creating Tests with the Traffic Inspector
One last tip before we finish this tutorial, there's a quicker way to create tests than via the interface in case you already have an application that's using the SOAP API.
If you have the ability to edit your application that's using the SOAP API, you can change its URL to a Runscope Traffic Inspector URL, and capture those requests. That way, you can just go to your bucket, head over to the Traffic tab, and then convert those requests into tests. That can be a quicker and easier way to create properly formatted SOAP requests for your API.
You can learn more about how to use the Traffic Inspector in our documentation.
Testing and monitoring SOAP APIs is as easy and important as maintaining REST APIs. Whether they are legacy systems or external dependencies that you have to support, you can rely on Runscope to make sure everything is going to be 200 OK®.
If you need any help creating your SOAP API tests, please reach out to our awesome support team.