This In-depth Tutorial Explains How to Get Started with REST API Testing With Spring RestTemplate And TestNG With Simple Examples:
In this article, we will see how to get started with REST API Testing with RestTemplate and TestNG framework.
Before exploring REST API Testing with RestTemplate and TestNG framework, let us understand some of the basic concepts involved in it.
Let’s Start!!
Table of Contents:
What is REST?
Nowadays, REST has become a quite popular choice of building Web Services. For Example, Google has multiple REST services like Calendar, Map API, etc.
REST i.e. Representational State Transfer is a software architectural style. In this style, a set of constraints is defined and web services built are required to satisfy these constraints. Such web services conforming REST architectural style are known as RESTful Web Services.
The term “Representational state transfer” was first put forward by Roy Fielding in his Ph.D. dissertation in the year 2000. The basic idea of REST is to treat server-side objects as resources that can be created or deleted.
What Is JSON?
JSON i.e. JavaScript Object Notation is a very commonly used syntax in REST services for storing and exchanging data between the browser and server.
The main advantage of JSON is its lightweight and secondly, its readable format too. Data is stored in the key: value pair format. For Example, you can have the employee data stored in JSON format like this: {“name”:”Emp1″,”salary”:”3000″,”age”:”23″,”id”:”52686″}.
What Is REST API Testing?
When we say REST API testing, it’s basically testing API by performing Create, Edit, Read, and Delete actions on Resource with 4 major methods i.e. POST, GET, PUT, and DELETE respectively
What Is TestNG?
TestNG is a testing framework that is inspired by JUnit and NUnit. It’s for the Java programming language. TestNG covers a wider range of test categories like unit, functional, end-to-end, integration, etc.
It’s an open-source framework that comes under the Apache License. It provides a rich set of annotations that accelerate the test script development.
What Is Spring REST Template?
Spring RestTemplate class is a part of the spring-web which was introduced in Spring 3
RestTemplate class provides a very convenient way to test the HTTP based restful web services by providing overloaded methods for HTTP methods like GET, POST, PUT, DELETE, etc. Spring framework is also open-source.
Further Reading => Best Spring Interview Questions
REST API Testing Steps
Let us understand the steps that are usually followed in REST API Testing with some examples to get a clear understanding.
In this article, I have considered one sample REST API employee service from this source.
Initially, let us follow the steps manually using the POSTMAN tool.
#1) First, know the endpoint of the API that you want to access.
For Example, http://dummy.restapiexample.com/api/v1/create to Create a new employee resource
#2) Set Headers and Body if required for the HTTP method.
In our example, as we are trying to create a new resource using POST. For POST, a request body is required.
So we will set the body as follows:
“name”:”zozo100″,”salary”:”123″,”age”:”23″
Accept: application/JSON and Content-Type: application/JSON.
#3) Set the appropriate HTTP method i.e. POST in this case.
#4) Send a request to the Rest service server.
#5) Receive a response from the server.
REST API Call Using The POSTMAN Tool
#6) Verify the Response as expected with the help of the Response Code E.g. 200 OK as a success.
#7) Verify the Response Body as expected if required by comparing it with your benchmark file.
Now, we have to automate the same steps for our Test Automation suite. Let us start with the setup required for automation.
Setting Up TestNG Test Framework On Windows
#1) Installation
- We are going to use Java for test script development. So, First Download JDK installer for windows and Install Java on your machine.
- IDE (Integrated Development Environment): I have used Eclipse as IDE for my Automation Test Suite development. Click here to download it.
- Get Eclipse Plug-in for TestNG: Note that Java 1.7+ is required for running TestNG for the Eclipse plug-in. Eclipse 4.2 and above is required. Follow the below steps in Eclipse :
- Select Help / Install New Software.
- Click on Add -> Enter http://beust.com/eclipse/
- Select the checkbox next to the URL and click on the Next button.
TestNG Installation
- Keep clicking on the Next Button, till you reach the following screen.
TestNG Installation Final Screen
Finally, accept the Apache License Agreement and click on the Finish button to complete the installation.
Restart Eclipse to take the plug-in installation in effect.
- Spring Jars: Now one more last thing, we are going to use the RestTemplate class from the spring framework. You can download spring jars and save it to a local folder, For Example, C:/projectJar
- JSON-Simple Jars: We need to perform JSON parsing. For that, we will use a lightweight Json-simple API. So, Download Json-simple-1.1.jar to C:/projectJar
Now we have completed the necessary installations. So, let us create our Test Automation project.
#2) Project Setup
- Create File -> New -> Java Project -> Name it as ‘EmployeeTestSuite’.
- Now, Create new java package com.demo:
- Configure Build Path:
- As you have seen in the earlier section, we have installed TestNG, downloaded spring and JSON-simple jars. So, now we have to add build path in our project to consume those. For that, create a lib folder in the EmployeeTestSuite folder and now copy all jars from the C:/projectJar to the lib folder.
- Right-click on ‘EmployeeTestSuite’’ -> Build Path -> Configure Build Path.
- Click on the lib tab.
- Click on the Add Library button -> Select TestNG. This will add TestNG to the build path.
- Click on Add jars button -> Select all jars from lib. This will add all spring jars and JSON-simple jar to your project build path.
Java Build Path
Your project structure will be displayed as follows in the Eclipse Package Explorer now.
Package Structure
#3) Test Class
We need to create a Test class which can cover CRUD (Create-Read-Update-Delete) Operations.
Create new class File -> New -> TestNG class, and name it TestCRUD.java
#4) Test Method
Let us create separate test methods:
- addEmployee(): Test Method to test Create API using the HTTP POST method.
- getEmployee (): Test Method to test Read API using the HTTP GET method.
- updateEmployee (): Test Method to test Update API using the HTTP PUT method.
- deleteEmployee (): Test Method to test Delete API using the HTTP DELETE method.
You can create a test method as any java method only with @Test annotation of TestNG to get it identified as the test method by the TestNG framework
For Example, the following is the addEmployee test method.
@Test public void addEmployee () {}
In our example, I have used a sample REST Service.
Now let us automate the POST call. For that, we need to map our code with the steps that we followed manually in the ‘REST API Testing Steps’ section one by one.
#1) First, know the endpoint of the API which you want to access.
String addURI = "http://dummy.restapiexample.com/api/v1/create";
#2) Set Headers for the HTTP method.
HttpHeaders headers = new HttpHeaders();
//Add headers
headers.add("Accept", "application/json"); headers.add("Content-Type", "application/json");
Set Body for the HTTP method.
String jsonBody = "{\"name\":\"zozo100\",\"salary\":\"123\",\"age\":\"23\"}";
//Create a HttpEntity object by setting body and headers.
HttpEntity<String> entity = new HttpEntity<String>(jsonBody, headers);
We will have the following steps automated in one statement.
#3) Set the appropriate HTTP method i.e. POST in this case.
#4) Send a request to the RESTful service server.
#5) Receive a response from the server.
RestTemplate restTemplate = new RestTemplate(); ResponseEntity<String> response =restTemplate.postForEntity(addURI, entity, String.class);
We are using postForEntity to send the POST method to the server. We receive the response from the server ResponseEntity<String> object.
#6) Verify the Response as expected with the help of the Response Code.
Assert.assertEquals(response.getStatusCode(), HttpStatus.OK);
Here, we are using the Assert tool class of TestNG to verify the status code assertEquals method that compares the actual value i.e. response.getStatusCode(), with the expected value HttpStatus.OK.
But here, we are doing one more verification i.e. Verifying if the added Employee is present in the response body or not.
Assert.assertTrue(responseBody.contains(employeeId));
How did we get the employeeId?
For this, we are taking the help of JSON parser API i.e. Json-simple.
We are using JSON parser, as JSON format is used for store and exchanging the data between the client and our server in our employee REST service. As mentioned earlier, JSON data is stored in key: value format. Here, we want to get the “id” value.
We will be getting it by parsing the response body as follows:
JSONParser parser = new JSONParser(); // Instantiate JSONParser object JSONObject jsonResponseObject = new (JSONObject) parser.parse(jsonString); //Parse jsonString i.e. Response body string in json format to JSON object String employeeId = jsonResponseObject.get("id").toString(); // Get id attribute
So, this is all about the Create method test.
Update, Get And Delete Methods
- Create separate test methods and set Headers as applicable.
- Verification of Status code is also done similarly.
- The main difference is the Methods for sending a request to the servers.
You can use the following methods:
#1) Update Employee: It is the HTTP PUT request. The RestTemplate PUT method that you can use is:
public void put(String url,Object request, Object... urlVariables) throws RestClientException
#2) Get Employee: It is the HTTP GET request. The RestTemplate GET method that you can use is as follows:
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... urlVariables) throws RestClientException
#3) Delete Employee Resource: It is the HTTP DELETE request. The RestTemplate DELETE method that you can use is:
public void delete(String url, Object... urlVariables) throws RestClientException
Apart from these methods, there are exchange() and execute() useful methods.
For Example, if you notice, the Delete method is void. But if you want to verify the response body, then you would need a response back from the method execution. For that purpose, you can use exchange () method that returns ResponseEntity. Refer to the Spring framework for more details.
#5) Running The Tests
Now, we have completed our test script development task, so let’s run our tests. Just right-click on TestCRUD.java and select the option ‘Run as TestNG Test’.
This will display test execution results as follows.
Console Output
Note: You can define your test suite in testng.xml file as well. In our example, it’s only One Test Script. But in the real scenario, it’s always a collection of multiple scripts.
So your testg.xml file will look as follows:
&amp;amp;amp;lt;! DOCTYPE suite SYSTEM &amp;amp;quot;http://testng.org/testng-1.0.dtd&amp;amp;quot; &amp;amp;amp;gt; &amp;amp;amp;lt;suite name=&amp;amp;quot;Employee_RestApi_Suite&amp;amp;quot;&amp;amp;amp;gt; &amp;amp;amp;lt;test name=&amp;amp;quot;TestCRUD&amp;amp;quot;&amp;amp;amp;gt; &amp;amp;amp;lt;classes&amp;amp;amp;gt; &amp;amp;amp;lt;class name=&amp;amp;quot;com.demo.TestCRUD&amp;amp;quot; /&amp;amp;amp;gt; &amp;amp;amp;lt;/classes&amp;amp;amp;gt; &amp;amp;amp;lt;/test&amp;amp;amp;gt; &amp;amp;amp;lt;/suite&amp;amp;amp;gt;
#6) Reports
We have seen the result on the console. But TestNG provides test results in a more presentable html format which can be shared with your stakeholders. Open test-output-> emailable-report.html in the browser.
You will see the test report as follows. In the report page, you can see the Test name as TestCRUD, several passed tests i.e. 4, Number of Skipped and Failed which are 0 in this case. It also shows the total time required for each test method execution.
Test Result In Html Format
Complete TestCRUD File Code
package com.demo; import java.io.IOException; import java.text.ParseException; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import org.testng.Assert; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import org.testng.log4testng.Logger; /** * This test class has test methods for CRUD actions on REST API * REST Service http://dummy.restapiexample.com/api * * It has test methods for Create , Edit , Get and Delete Employee items * https://docs.spring.io/spring-framework/docs/current/javadoc- api/org/springframework/web/client/RestTemplate.html * https://docs.spring.io/autorepo/docs/spring/3.2.3.RELEASE/javadoc- api/org/springframework/web/client/RestTemplate.html * @author * */ public class TestCRUD { private String responseBody; public String responseBodyPOST; final static Logger logger = Logger.getLogger(TestCRUD.class); //RESTTemplate Object private RestTemplate restTemplate; //Employee ID private String employeeId; // Create Response Entity - Stores HTTPStatus Code, Response Body, etc private ResponseEntity&amp;amp;amp;lt;String&amp;amp;amp;gt; response; @BeforeTest public void beforeTest() throws IOException, ParseException { logger.info(&amp;amp;quot;Setting up prerequisite for test execution&amp;amp;quot;); logger.info(&amp;amp;quot;Creating RestTemplate object before tests&amp;amp;quot;); this.restTemplate = new RestTemplate(); } /** * Test Method to add employee using HTTP POST request * * Verifies POST action Status Code * * @throws IOException * @throws ParseException */ @Test public void addEmployee() throws IOException, ParseException { String addURI = &amp;amp;quot;http://dummy.restapiexample.com/api/v1/create&amp;amp;quot;; HttpHeaders headers = new HttpHeaders(); headers.add(&amp;amp;quot;Accept&amp;amp;quot;, &amp;amp;quot;application/json&amp;amp;quot;); headers.add(&amp;amp;quot;Content-Type&amp;amp;quot;, &amp;amp;quot;application/json&amp;amp;quot;); logger.info(&amp;amp;quot;Add URL :&amp;amp;quot;+addURI); String jsonBody = &amp;amp;quot;{\&amp;amp;quot;name\&amp;amp;quot;:\&amp;amp;quot;zozo100\&amp;amp;quot;,\&amp;amp;quot;salary\&amp;amp;quot;:\&amp;amp;quot;123\&amp;amp;quot;,\&amp;amp;quot;age\&amp;amp;quot;:\&amp;amp;quot;23\&amp;amp;quot;}&amp;amp;quot;; System.out.println(&amp;amp;quot;\n\n&amp;amp;quot; + jsonBody); HttpEntity&amp;amp;amp;lt;String&amp;amp;amp;gt; entity = new HttpEntity&amp;amp;amp;lt;String&amp;amp;amp;gt;(jsonBody, headers); //POST Method to Add New Employee response = this.restTemplate.postForEntity(addURI, entity, String.class); responseBodyPOST = response.getBody(); // Write response to file responseBody = response.getBody().toString(); System.out.println(&amp;amp;quot;responseBody ---&amp;amp;amp;gt;&amp;amp;quot; + responseBody); // Get ID from the Response object employeeId = getEmpIdFromResponse(responseBody); System.out.println(&amp;amp;quot;empId is :&amp;amp;quot; + employeeId); // Check if the added Employee is present in the response body. Assert.assertTrue(responseBody.contains(employeeId)); // System.out.println(propertyFile.get(&amp;amp;quot;EmployeeAddResBody&amp;amp;quot;)); // Check if the status code is 201 Assert.assertEquals(response.getStatusCode(), HttpStatus.OK); logger.info(&amp;amp;quot;Employee is Added successfully employeeId:&amp;amp;quot;+employeeId); } /** * Method to get Employee ID from REsponse body * I have used Json Simple API for Parsing the JSON object * * @param json * @return */ public static String getEmpIdFromResponse(String json) { JSONParser parser = new JSONParser(); JSONObject jsonResponseObject = new JSONObject(); Object obj = new Object(); try { obj = parser.parse(json); } catch (org.json.simple.parser.ParseException e) { e.printStackTrace(); } jsonResponseObject = (JSONObject) obj; String id = jsonResponseObject.get(&amp;amp;quot;id&amp;amp;quot;).toString(); return id; } /** * Test Method to Update employee using HTTP PUT request * * Verifies PUT action Status Code * Verifies Updated Name exists in Response Body * * @throws IOException * @throws ParseException */ @Test(dependsOnMethods = &amp;amp;quot;addEmployee&amp;amp;quot;, enabled = true) public void updateEmployee() throws IOException, ParseException { String updateURI = &amp;amp;quot;http://dummy.restapiexample.com/api/v1/update/&amp;amp;quot;+employeeId; logger.info(&amp;amp;quot;Update URL :&amp;amp;quot;+updateURI); String jsonBody = responseBodyPOST; jsonBody = jsonBody.replace(&amp;amp;quot;zozo100&amp;amp;quot;, &amp;amp;quot;update_zozo100&amp;amp;quot;); HttpHeaders headers = new HttpHeaders(); headers.add(&amp;amp;quot;Accept&amp;amp;quot;, &amp;amp;quot;application/json&amp;amp;quot;); headers.add(&amp;amp;quot;Content-Type&amp;amp;quot;, &amp;amp;quot;application/json&amp;amp;quot;); HttpEntity&amp;amp;amp;lt;String&amp;amp;amp;gt; entity = new HttpEntity&amp;amp;amp;lt;String&amp;amp;amp;gt;(jsonBody, headers); //PUT Method to Update the existing Employee //NOTE that I have Not used restTemplate.put as it's void and we need response for verification response = restTemplate.exchange(updateURI, HttpMethod.PUT, entity, String.class); responseBody = response.getBody().toString(); System.out.println(&amp;amp;quot;Update Response Body :&amp;amp;quot;+responseBody); // Check if the updated Employee is present in the response body. Assert.assertTrue(responseBody.contains(&amp;amp;quot;update_zozo100&amp;amp;quot;)); // Check if the status code is 200 Assert.assertEquals(response.getStatusCode(), HttpStatus.OK); logger.info(&amp;amp;quot;Employee Name is Updated successfully employeeId:&amp;amp;quot;+employeeId); } /** * Test Method to Get employee using HTTP GET request * * Verifies GET action Status Code * Verifies Name exists in Response Body * * @throws IOException * @throws ParseException */ @Test(dependsOnMethods = &amp;amp;quot;updateEmployee&amp;amp;quot;, enabled = true) void getEmployee() throws IOException, ParseException { String getURI = &amp;amp;quot;http://dummy.restapiexample.com/api/v1/employee/&amp;amp;quot;+this.employeeId; logger.info(&amp;amp;quot;Get URL :&amp;amp;quot;+getURI); HttpHeaders headers = new HttpHeaders(); HttpEntity&amp;amp;amp;lt;String&amp;amp;amp;gt; entity = new HttpEntity&amp;amp;amp;lt;String&amp;amp;amp;gt;(headers); //GET Method to Get existing Employee response = restTemplate.getForEntity(getURI,String.class); // Write response to file responseBody = response.getBody().toString(); //Suppressing for log diffs System.out.println(&amp;amp;quot;GET Response Body :&amp;amp;quot;+responseBody); // Check if the added Employee ID is present in the response body. Assert.assertTrue(responseBody.contains(&amp;amp;quot;update_zozo100&amp;amp;quot;)); // Check if the status code is 200 Assert.assertEquals(response.getStatusCode(), HttpStatus.OK); logger.info(&amp;amp;quot;Employee is retrieved successfully employeeId:&amp;amp;quot;+employeeId); } /** * Test Method to Delete employee using HTTP DELETE request * * Verifies DELETE action Status Code * Verifies Success Message Text in Response Body * * @throws IOException * @throws ParseException */ @Test(dependsOnMethods = &amp;amp;quot;getEmployee&amp;amp;quot;, enabled = true) public void deleteEmployee() throws IOException, ParseException { String delURI = &amp;amp;quot;http://dummy.restapiexample.com/api/v1/delete/&amp;amp;quot;+this.employeeId; HttpHeaders headers = new HttpHeaders(); HttpEntity&amp;amp;amp;lt;String&amp;amp;amp;gt; entity = new HttpEntity&amp;amp;amp;lt;String&amp;amp;amp;gt;(headers); //DELETE Method to Delete existing Employee response = restTemplate.exchange(delURI, HttpMethod.DELETE, entity, String.class); // Check if the status code is 204 Assert.assertEquals(response.getStatusCode(), HttpStatus.OK); responseBody = response.getBody(); Assert.assertEquals(getMessageFromResponse(responseBody), &amp;amp;quot;successfully! deleted Records&amp;amp;quot;); logger.info(&amp;amp;quot;Employee is Deleted successfully employeeId:&amp;amp;quot;+employeeId); } /** * Gets &amp;amp;quot;text&amp;amp;quot; key value from Response body text for verification * I have used Json Simple API for Parsing the JSON object * * @param json * @return text string */ public static String getMessageFromResponse(String json) { String successMessageText = null; try { JSONParser parser = new JSONParser(); JSONObject jsonResponseObject = new JSONObject(); jsonResponseObject = (JSONObject) (parser.parse(json)); String successMessage = jsonResponseObject.get(&amp;amp;quot;success&amp;amp;quot;).toString(); jsonResponseObject = (JSONObject) (parser.parse(successMessage)); successMessageText = jsonResponseObject.get(&amp;amp;quot;text&amp;amp;quot;).toString(); } catch (org.json.simple.parser.ParseException e) { e.printStackTrace(); } return successMessageText; } @AfterTest public void afterTest() { logger.info(&amp;amp;quot;Clean up after test execution&amp;amp;quot;); logger.info(&amp;amp;quot;Creating RestTemplate object as Null&amp;amp;quot;); this.restTemplate = new RestTemplate(); } }
Conclusion
We have summarized the learning outcome of this article below. We saw all the steps from the beginning to set up a REST API Test Automation Framework.
In this we learned the following:
- For test automation, we selected Java as a programming language.
- We chose TestNG as the test framework for creating a test script where we consumed TestNG annotations like @Test.
- For sending actual HTTP requests to the server, we consumed the Spring framework RestTemplate class.
- For consuming these APIs, we did the installation of TestNG, downloaded Spring jars and Json-simple jar for the parser API.
- Finally, we executed the Test class and saw the result on the console as well as in a more presentable and more readable HTML format.
In a nutshell, in this article, we learned how to get started with REST API Test automation with Spring RestTemplate. We covered setting up our test automation framework starting from Installation of all essential software, Project Setup, Test Script development till Test execution and viewing the generated reports.
This is fairly sufficient for any automation QA to get started with your test automation framework. But, we have seen only the required parts from each, For Example, we have used TestNG installation, test method using @Test annotation, reports. However, TestNG provides many more features like DataProvider for Data-driven testing, etc.
Are you ready to get started with REST API Test automation with Spring RestTemplate?