Validating Response body in RestAssured - Notes By ShariqSP
API Response Assertion Guide
When testing APIs, it's crucial to assert the response body to ensure data integrity and correctness. Below, we demonstrate how to perform assertions on the response body of the GET API endpoint:
http://apitesting.shariqsp.com:8080/api/companies
Response JSON Structure
{
"name": "TechCorp",
"location": "New York",
"phone": "+1234567890",
"email": "contact@techcorp.com",
"lastUpdated": "2024-11-25T07:17:36.204Z",
"mobileItems": [
{
"brand": "Samsung",
"model": "Galaxy S23 Ultra",
"price": 1199.99,
"currency": "USD",
"specifications": {
"processor": "Snapdragon 8 Gen 2",
"ram": "12GB",
"storage": "256GB",
"rearCamera": "200MP",
"frontCamera": "40MP",
"battery": 5000,
"os": "Android 13"
},
"warranty": {
"coverage": "Manufacturer",
"duration": 2
},
"availability": [
{
"store": "Best Buy",
"stock": 25
},
{
"store": "Amazon",
"stock": 50
}
]
}
]
}
Understanding JSONPath and Assertions
JSONPath is a query language to access specific parts of a JSON document. It works like XPath for XML. Common JSONPath expressions include:
$: Refers to the root of the JSON.$.name: Fetches the "name" property from the root.$.mobileItems[0].brand: Fetches the "brand" of the first mobile item.$.mobileItems[0].availability[*].store: Fetches all store names where the item is available.
Assertions for Different Data
Below are examples of assertions for validating the API response:
http://apitesting.shariqsp.com:8080/api/companies
1. Asserting Response Time
Ensure the response time is less than 2000 milliseconds:
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
public class APITests {
public static void main(String[] args) {
given()
.get("http://apitesting.shariqsp.com:8080/api/companies")
.then()
.assertThat()
.time(lessThan(2000L));
}
}
2. Asserting Response Status Code
Validate the response status code is 200:
given()
.get("http://apitesting.shariqsp.com:8080/api/companies")
.then()
.assertThat()
.statusCode(200);
3. Asserting JSON Response Data
Validate specific fields in the response JSON:
// Assert the company name
@Test
void testCompanyName() {
given()
.get("http://apitesting.shariqsp.com:8080/api/companies")
.then()
.assertThat()
.body("name[0]", Matchers.equalTo("TechCorp")); // Verify company name
}
@Test
void testCompanyLocation() {
given()
.get("http://apitesting.shariqsp.com:8080/api/companies")
.then()
.assertThat()
.body("location[0]", Matchers.equalTo("New York")); // Verify location
}
@Test
void testCompanyPhone() {
given()
.get("http://apitesting.shariqsp.com:8080/api/companies")
.then()
.assertThat()
.body("phone[0]", Matchers.equalTo("+1234567890")); // Verify phone number
}
@Test
void testCompanyEmail() {
given()
.get("http://apitesting.shariqsp.com:8080/api/companies")
.then()
.assertThat()
.body("email[0]", Matchers.equalTo("contact@techcorp.com")); // Verify email
}
@Test
void testLastUpdated() {
given()
.get("http://apitesting.shariqsp.com:8080/api/companies")
.then()
.assertThat()
.body("lastUpdated", Matchers.notNullValue()); // Verify last updated is not null
}
@Test
void testMobileItemBrand() {
given()
.get("http://apitesting.shariqsp.com:8080/api/companies")
.then()
.assertThat()
.body("mobileItems[0].brand[0]", Matchers.equalTo("Samsung")); // Verify first mobile item's brand
}
@Test
void testMobileItemModel() {
given()
.get("http://apitesting.shariqsp.com:8080/api/companies")
.then()
.assertThat()
.body("mobileItems[0].model[0]", Matchers.equalTo("Galaxy S23 Ultra")); // Verify first mobile item's model
}
@Test
void testMobileItemPrice() {
given()
.get("http://apitesting.shariqsp.com:8080/api/companies")
.then()
.assertThat()
.body("mobileItems[0].price[0]", Matchers.equalTo(1199.99f)); // Verify first mobile item's price
}
@Test
void testMobileItemSpecifications() {
given()
.get("http://apitesting.shariqsp.com:8080/api/companies")
.then()
.assertThat()
.body("mobileItems[0].specifications.processor[0]", Matchers.equalTo("Snapdragon 8 Gen 2"))
.body("mobileItems[0].specifications.ram[0]", Matchers.equalTo("12GB"))
.body("mobileItems[0].specifications.storage[0]", Matchers.equalTo("256GB"))
.body("mobileItems[0].specifications.rearCamera[0]", Matchers.equalTo("200MP"))
.body("mobileItems[0].specifications.frontCamera[0]", Matchers.equalTo("40MP"))
.body("mobileItems[0].specifications.battery[0]", Matchers.equalTo(5000))
.body("mobileItems[0].specifications.os[0]", Matchers.equalTo("Android 13")); // Verify mobile specifications
}
@Test
void testMobileItemWarranty() {
given()
.get("http://apitesting.shariqsp.com:8080/api/companies")
.then()
.assertThat()
.body("mobileItems[0].warranty.coverage[0]", Matchers.equalTo("Manufacturer"))
.body("mobileItems[0].warranty.duration[0]", Matchers.equalTo(2)); // Verify warranty details
}
@Test
void testAvailabilityBestBuy() {
given()
.get("http://apitesting.shariqsp.com:8080/api/companies")
.then()
.assertThat()
.body("mobileItems[0].availability[0].store[0]", Matchers.equalTo("Best Buy"))
.body("mobileItems[0].availability[0].store[1]", Matchers.equalTo("Amazon"))
.body("mobileItems[0].availability[0].stock[0]", Matchers.equalTo(25)) // Verify stock at Best Buy
.body("mobileItems[0].availability[0].stock[1]", Matchers.equalTo(50)); // Verify stock at Best Buy
}
@Test
void testAvailabilityAmazon() {
given()
.get("http://apitesting.shariqsp.com:8080/api/companies")
.then()
.assertThat()
.body("mobileItems[0].availability[1].store", Matchers.equalTo("Amazon"))
.body("mobileItems[0].availability[1].stock", Matchers.equalTo(50)); // Verify stock at Amazon
}
4. Validating JSON Array Size
Check the number of mobile items in the "mobileItems" array:
given()
.get("http://apitesting.shariqsp.com:8080/api/companies")
.then()
.assertThat()
.body("mobileItems.size()", greaterThan(0));
5. Asserting Response Headers
Ensure the response contains the correct Content-Type header:
given()
.get("http://apitesting.shariqsp.com:8080/api/companies")
.then()
.assertThat()
.header("Content-Type", "application/json");
6. Combining Multiple Assertions
Validate multiple properties in one test:
given()
.get("http://apitesting.shariqsp.com:8080/api/companies")
.then()
.assertThat()
.statusCode(200)
.time(lessThan(2000L))
.body("name", equalTo("TechCorp"))
.body("mobileItems[0].brand", equalTo("Samsung"));
7. Using JSONPath for Nested Data
To access deeply nested JSON data, JSONPath can be used in Rest-Assured. For example:
mobileItems[0].specifications.processor: Fetches the processor of the first mobile item.mobileItems[0].availability[0].store: Fetches the first store's name where the item is available.
Example of nested data validation:
given()
.get("http://apitesting.shariqsp.com:8080/api/companies")
.then()
.assertThat()
.body("mobileItems[0].specifications.processor", equalTo("Snapdragon 8 Gen 2"));
Using JSONPath Tools
To find JSON paths, you can use tools like:
- JSON path Finder
- Postman (when testing APIs)
- IDE plugins like IntelliJ JSONPath evaluator
Using JSONPath in XPath Format
XPath for JSON (used in some tools) has a similar hierarchy but is less common. For example:
//name: Fetches the "name" field.//mobileItems[1]/availability/store: Fetches the "store" names for the second item in "mobileItems".
Testing Stock Availability in API Response
This section describes how to test stock availability for a specific product in the API response using RestAssured and Hamcrest matchers. We will validate that the stock availability for a specific mobile item at a particular store is correct.
JSON Response
The JSON response from the API contains data about multiple companies, each with information on their mobile items, warranties, and availability at various stores. Below is the relevant part of the response:
[
{
"id": 1,
"name": "TechCorp",
"location": "New York",
"phone": "+1234567890",
"email": "contact@techcorp.com",
"lastUpdated": "2024-11-25T09:22:32.978411",
"mobileItems": [
{
"id": 1,
"brand": "Samsung",
"model": "Galaxy S23 Ultra",
"price": 1199.99,
"currency": "USD",
"specifications": {
"id": 1,
"processor": "Snapdragon 8 Gen 2",
"ram": "12GB",
"storage": "256GB",
"rearCamera": "200MP",
"frontCamera": "40MP",
"battery": 5000,
"os": "Android 13"
},
"warranty": {
"id": 1,
"coverage": "Manufacturer",
"duration": 2
},
"availability": [
{
"id": 1,
"store": "Best Buy",
"stock": 25
},
{
"id": 2,
"store": "Amazon",
"stock": 50
}
]
}
]
},
{
"id": 2,
"name": "GigaTech",
"location": "San Francisco",
"phone": "+1987654321",
"email": "contact@gigatech.com",
"lastUpdated": "2024-11-25T09:44:40.476194",
"mobileItems": [
{
"id": 2,
"brand": "Apple",
"model": "iPhone 15 Pro",
"price": 1499.99,
"currency": "USD",
"specifications": {
"id": 2,
"processor": "A17 Bionic",
"ram": "8GB",
"storage": "512GB",
"rearCamera": "48MP",
"frontCamera": "12MP",
"battery": 3500,
"os": "iOS 17"
},
"warranty": {
"id": 2,
"coverage": "AppleCare",
"duration": 3
},
"availability": [
{
"id": 3,
"store": "Apple Store",
"stock": 10
},
{
"id": 4,
"store": "Best Buy",
"stock": 40
}
]
}
]
},
{
"id": 3,
"name": "InnovateMobile",
"location": "Los Angeles",
"phone": "+1122334455",
"email": "support@innovatemobile.com",
"lastUpdated": "2024-11-25T09:44:55.92183",
"mobileItems": [
{
"id": 3,
"brand": "Google",
"model": "Pixel 8 Pro",
"price": 999.99,
"currency": "USD",
"specifications": {
"id": 3,
"processor": "Tensor G3",
"ram": "12GB",
"storage": "256GB",
"rearCamera": "50MP",
"frontCamera": "10.8MP",
"battery": 5000,
"os": "Android 14"
},
"warranty": {
"id": 3,
"coverage": "Google Warranty",
"duration": 2
},
"availability": [
{
"id": 5,
"store": "Google Store",
"stock": 35
},
{
"id": 6,
"store": "Target",
"stock": 25
}
]
}
]
},
{
"id": 4,
"name": "FutureTech",
"location": "Chicago",
"phone": "+1444332211",
"email": "hello@futuretech.com",
"lastUpdated": "2024-11-25T09:45:05.993028",
"mobileItems": [
{
"id": 4,
"brand": "OnePlus",
"model": "OnePlus 12",
"price": 899.99,
"currency": "USD",
"specifications": {
"id": 4,
"processor": "Snapdragon 8 Gen 3",
"ram": "16GB",
"storage": "512GB",
"rearCamera": "108MP",
"frontCamera": "32MP",
"battery": 6000,
"os": "OxygenOS 14"
},
"warranty": {
"id": 4,
"coverage": "OnePlus Warranty",
"duration": 1
},
"availability": [
{
"id": 7,
"store": "OnePlus Store",
"stock": 15
},
{
"id": 8,
"store": "Walmart",
"stock": 30
}
]
}
]
}
]
Test Code
The following test code uses RestAssured and Hamcrest matchers to verify that the stock for a specific mobile item (OnePlus 12 from FutureTech) at the Walmart store is equal to 30.
@Test
void testStockAvailability() {
given()
.get("http://apitesting.shariqsp.com:8080/api/companies")
.then()
.assertThat()
.body("[3].mobileItems[0].availability[1].stock", Matchers.equalTo(30)); // Walmart stock for FutureTech mobile
}
Explanation of the Test
The test performs the following actions:
- given(): This initiates the request. It sends a GET request to the URL "http://apitesting.shariqsp.com:8080/api/companies".
- then(): This checks the response returned by the server.
- assertThat(): This is where the assertions are applied to validate the response body.
- body(): The assertion checks the value at a specific JSON path. The path
[3].mobileItems[0].availability[1].stockrefers to the stock availability for the OnePlus 12 mobile item at Walmart for the FutureTech company. - Matchers.equalTo(30): The test asserts that the stock value for Walmart's availability is equal to 30. If this value is not 30, the test will fail.
JSON Path Breakdown
The JSON path expression used is [3].mobileItems[0].availability[1].stock. Here’s what it refers to:
- [3]: This refers to the 4th object in the array, which corresponds to the "FutureTech" company.
- mobileItems[0]: This accesses the first item in the "mobileItems" array, which corresponds to the "OnePlus 12" mobile.
- availability[1]: This accesses the second availability item in the "availability" array, which is for "Walmart".
- stock: This refers to the "stock" value for the "Walmart" store, which is expected to be 30.