Testing RESTful webservices

With the world of IT systems and applications becoming more and more distributed, testing the interfaces between system components becomes ever more important. In a previous post I have introduced a very basic way to test a SOAP web service interface. However, nowadays, in the world of APIs, the REpresentational State Transfer or REST standard becomes increasingly popular due to its lightweight nature. This article introduces a way to test RESTful APIs in a simple yet effective manner, and in a way that integrates smoothly with your existing Java-based testing frameworks, such as those based on Selenium Webdriver.

RESTful APIs come in several varieties. In this post, we are going to see two of them: one returning XML responses (I used this one) and one returning JSON responses (I used this one). You’re welcome to click on either link to see the difference in response format.

Also, I have used some external libraries to get the code to work:

Verify the HTTP status code
The first thing we are going to test for our services is whether they respond to our requests at all. This means we are going to validate whether the HTTP response code for the REST service is correct. There way to do this is equal for both XML and JSON REST APIs:

public static void testStatusCode(String restURL) throws ClientProtocolException, IOException {

	HttpUriRequest request = new HttpGet(restURL);
	HttpResponse httpResponse = HttpClientBuilder.create().build().execute(request);
		
	Assert.assertEquals(httpResponse.getStatusLine().getStatusCode(),HttpStatus.SC_OK);
}

Pretty simple, right? As you probably know, calling a RESTful API is done by either sending a HTTP POST or a HTTP GET to a specific URL. This in contrast with SOAP web services, where you send a specific XML message to an endpoint. Then, retrieve the HTTP status code from the response and check whether this is OK (i.e., equal to HTTP 200).

Verify the response content type
Next, we are going to verify whether our web service sends us the content type we expect (either XML or JSON). Again, this can be done with just a couple of lines of code:

public static void testMimeType(String restURL, String expectedMimeType) throws ClientProtocolException, IOException {
		
	HttpUriRequest request = new HttpGet(restURL);
	HttpResponse httpResponse = HttpClientBuilder.create().build().execute(request);
		
	Assert.assertEquals(expectedMimeType,ContentType.getOrDefault(httpResponse.getEntity()).getMimeType());
}

Again, just call the RESTful API URL and retrieve the information you need from the response. In this case, we are interested in the MIME type, which should be either ‘application/xml’ or ‘application/json’, depending on the URL we use.

Verify the response content
Now that we have verified whether our services return correct responses with the correct MIME type, it’s time to look at the actual content of the response. This is where testing XML RESTful APIs differs from testing JSON RESTful APIs, since we need to parse the response to extract the elements and element values we’re interested in.

For XML, we can do this using the following piece of code:

public static void testContent(String restURL, String element, String expectedValue) throws ClientProtocolException, IOException, SAXException, ParserConfigurationException {
		
	Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(restURL);
	NodeList nodelist = doc.getElementsByTagName(element);
		
	Assert.assertEquals(expectedValue,nodelist.item(0).getTextContent());		
}

Note that we use a different way to retrieve the result from the REST URL as we need to parse it as actual XML. After we’ve done that, we simply look for the XML element we’re interested in and compare its value to the value we expect.

For JSON, we can verify element values as follows:

public static void testContentJSON(String restURL, String element, String expectedValue) throws ClientProtocolException, IOException, SAXException, ParserConfigurationException, JSONException {

	HttpUriRequest request = new HttpGet(restURL);
	HttpResponse httpResponse = HttpClientBuilder.create().build().execute(request);

	// Convert the response to a String format
	String result = EntityUtils.toString(httpResponse.getEntity());

	// Convert the result as a String to a JSON object
	JSONObject jo = new JSONObject(result);

	Assert.assertEquals(expectedValue, jo.getString(element));
}

Here, we need to take an intermediate step to parse the response to a sensible format. First, we convert the HttpResponse to a String, then we convert this String to a JSONObject. From this JSONObject we can then extract the value for a specific element and compare it to an expected value.

The above examples should get you started nicely when you’re asked to include testing RESTful web services in your automated testing solutions.

Again, happy testing!

An example Eclipse project where I use the code above can be downloaded here.

56 thoughts on “Testing RESTful webservices

    • Thanks again for the suggestions, Phil. Even though both APIs I used are accessible to the world as well, the Flickr one might indeed be an interesting one for the readers to go and experiment with.

  1. Hi Bas,

    Thanks for your detail sharing. But I still get an error while run your scripts in eclipse.
    Error on “WebDriver androidDriver = new SelendroidDriver(capa);”
    *********java.lang.NoSuchMethodError: org.openqa.selenium.remote.CommandInfo.(Ljava/lang/String;Lorg/openqa/selenium/remote/http/HttpMethod;)V *********************
    I don’t know what did the error mean, I’m all using 0.11.0 version?

    One question: Why there is resigned-selendroid-test-app-0.11.0.apk, do I need to install this apk in android emulator? I don’t understand what’s this apk used for?

    Please help me on that, thanks in advance.

    Regards,
    Fion

  2. Hi Bas,

    How to trigger HTTP request with username/pwd when the API requires username and password for authentication?

    Thank you in advance.

    Regards,
    Neel.

  3. Hi,

    I am new to api testing, i am asked to write script to test the backend rest based services for a mobile app(android). Your post was helpful to me. Should I have to add any jar files for verifying the http status and other process hence after.

    Regards
    Anshuman

    • Hi Anshuman,

      if all you need to test is the REST backend services, and you don’t have to deal with the UI, then you don’t need Appium or Selendroid. In fact, using those would only introduce unncessary overhead. I think it would be a good idea to look into REST Assured, it’s easy to use and I think you’ll like it!

  4. Thanks this was very helpful. However I am trying to do the same in Ruby do you have any resources that you can point me to thanks Nilesh.

    • You need to use PostMethod() for that. The easiest way is probably to use this one.

      An example of its usage can be found here. I’m sure you can adapt this to fit your needs.

  5. Hi Bas,

    I am new to API automation testing. I using eclipse tool for API automation testing. I don’t have any idea of that. So can you explain eclipse tool process or how it’s working.
    Please help.

    Thank you,
    Suchandra.

    • Hi Suchandra,

      I think you’re confusing two different things here.. Eclipse is a tool to support development productivity (also called an Integrated Development Environment or IDE), not a test tool. You can write tests in a test tool such as REST Assured for RESTful APIs using Eclipse or any other IDE).

      Hope that clears some things up for you..

      • Hello Bas,

        Sorry for that. Thank you for reply. There is TestNG for Selenium. Is that correct?

        Thank you.

        • No, TestNG is a Java unit testing framework, Selenium is a browser automation framework that is available in many programming languages, among them Java. They can be combined into a single testing framework though, something that I’ve successfully done in the past.

  6. Hi Bas,
    Can we use selenium and do API testing.
    Can Backend testing acually be done using Selenium?

    Thanks in advance. 🙂

    • Hi Vijita,

      Selenium is purely meant for automating browser interaction. If you want to talk to an API you’ll need to use something else, such as REST Assured (if you use Java). Both can be combined within one single testing framework, though.

  7. Hi BAS,
    Greetings..
    I really appreciate for your sharing’s and quick replies.
    I would like to learn the API testing automation with SOAP as well as REST. Can you please guide me from where I can learn it to have a strong foundation in web service Testing? Thanks

    • Hi Aneesh,

      as a general introduction into API testing I always recommend the SoapUI API testing dojo. It covers a lot of the topics you mention. Have fun reading and please let me know if after reading that you need other resources.

  8. HI Bas,

    Greetings….
    Thanks for Great info.i need some info about webservice automation using Ruby-Cucumber(RubyMine) .Any idea you have regarding this.

    • Hey Zilu,

      thanks for your kind words. I have no experience with Ruby whatsoever, but Cucumber is a BDD framework and RubyMine is an IDE as far as I know.. So to be able to write tests for web services in Ruby you’ll need some other gem / library. As I have never used Ruby myself I don’t think I’m the right person to ask this question to.. Sorry!

  9. Hi Bas,

    How can we send media file attachment with POST method? I want to upload a media file using POST method. How can we do this?

    • Hi Monendra,

      if you use REST Assured instead of the approach I suggested in my post it’s actually pretty easy judging from this blog post from the creator of REST Assured.

      If you want to do it programmatically yourself, check out this site, specifically the ‘Multipart encoded request entity’ example.

  10. Pingback: RESTful services automated testing – SelvaSantosh

  11. When i execute the test using below method, i get the error “JSONObject[“name”] not found” . Not able to pick the individual element from JSON output

    @Test()
    public static void testContent() throws ClientProtocolException, IOException, SAXException, ParserConfigurationException, Exception
    {

    HttpUriRequest request = new HttpGet(“http://services.groupkt.com/country/get/all”);
    HttpResponse httpResponse = HttpClientBuilder.create().build().execute(request);
    String restresult = EntityUtils.toString(httpResponse.getEntity());
    JSONObject parentObject = new JSONObject(restresult);
    Assert.assertEquals(“Afghanistan”, parentObject.getString(“name”));

    }

    }

  12. Hey Bas,

    Thank you very much for this article.
    I find it helpful.
    My requirement is somewhat different.
    I have a web application based on django framework.
    I have made framework using selenium (Java).
    I am logging into application using my framework. and then there is a page which contains data which is coming from back end in json format.
    My requirement is to log in through selenium as usual and when i land on that page i should be able to pull out json and deserialise it to proceed with my further validation.

    I hope I am able to make myself clear.

    Request you to please help me in this regard.

    Thanks & Regards..
    Shashi Chowrasia

    • Hi Shashi,

      thanks for the kind words!

      There is one problem: once you’ve landed on the page that shows the JSON data, it has already been retrieved from the server and interpreted by the front-end. The scenario you’re proposing therefore doesn’t really make sense to me. Instead, you could check either that:

      * The web page correctly displays the data returned by the backend, OR
      * The backend returns the correct data

      You seem to be doing a bit of both at the moment. For the first option, Selenium is a good way to go. For the second option, I think it would be better to retrieve the data directly from the backend through an API call, capture the JSON and validate it. You could use a tool like REST Assured for that, for example.

  13. Hey Bas, can we test REST client & SOAP client using selenium, if then how can we test and write a script. Can u plz suggest me on this.

    Regards,
    Keerthi

  14. Hi Bas,
    My requirement is to automate both ui as well as rest service api validation for a web based project . Can I achieve this with help of selenium.If yes how can I integrate the UI as well as the REST api validation in a single flow to complete an end to end testing

    Thanks,
    Arun

    • Hi Arun,

      sure. Are you using Java? Then you could for example create a solution that uses Selenium for the UI stuff, and a tool like REST Assured for the RESTful API part. Your test itself can then simply be a sequence like this:

      @Test
      public void testStuff() {
      doSomeSeleniumStuff();
      doSomeRestAssuredStuff();
      doSomeMoreSeleniumStuff();
      }

      • Thanks BAS.I have implemented the code but while executing as JAVA program am getting a run time error like

        java.net.UnknownHostException: api.openweathermap.org
        at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
        at java.net.InetAddress$2.lookupAllHostAddr(Unknown Source)
        at java.net.InetAddress.getAddressesFromNameService(Unknown Source)
        at java.net.InetAddress.getAllByName0(Unknown Source)
        at java.net.InetAddress.getAllByName(Unknown Source)
        at java.net.InetAddress.getAllByName(Unknown Source)
        at org.apache.http.impl.conn.SystemDefaultDnsResolver.resolve(SystemDefaultDnsResolver.java:45)
        at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:112)
        at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:359)
        at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:381)
        at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:237)
        at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
        at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
        at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111)
        at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
        at rest.RESTTester.testStatusCode(RESTTester.java:62)
        at rest.RESTTester.main(RESTTester.java:35) for JSON response .

    • Just add the required dependencies to your project. I think I’ve mentioned them in the post. Sorry, this was before I knew how to set up a proper Maven project.

      • Thanks Bas. I did add the dependencies.
        Is there an example to use cucumber feature to restful services and another example to test webservices using cucumber. It should be complete package with feature file,step definition,runner class,yml or using pipes within cucumber and coding.

        This would really help in knowing how to implement cucumber/gherkin in webservices and restful services testing.
        Thanks a ton for your help

  15. i have one simple question, when we have angular UI application which has dynamic attributes for class or id then when we automate using protractor do we face the flaky UI if we run same test multiple times

    • Potentially, yes. Better to focus on element properties that do not change every time a page is rendered.

      Also, could you please comment on a post that’s relevant to your question?

  16. Hi,

    Thank you for sharing this post but I still have a doubts that what to do when we want to compare JSON file data with selenium?

Leave a Reply

Your email address will not be published. Required fields are marked *