Testing a REST API is more than just sending a request and expecting a 200 OK. You need to verify the API's functionality, structure, performance, and reliability under various conditions. Here’s a breakdown of what should be tested during API automation.
Headers carry important metadata between client and server. They influence how requests are processed and how responses are interpreted.
Common headers to verify:
Authorization: Validates the user identity (e.g., Bearer token)
Content-Type: Specifies format of the request payload (e.g., application/json)
Accept: Defines what content types the client expects
X-Client-Version: Custom client versioning headers
What to Test:
Presence and correctness of mandatory headers
Validation of header values
Impact of missing, malformed, or invalid headers
HTTP status codes indicate the result of the request.
Common HTTP Code Categories:
1xx – Informational
2xx – Success (e.g., 200 OK, 201 Created)
3xx – Redirection
4xx – Client error (e.g., 400 Bad Request, 401 Unauthorized)
5xx – Server error (e.g., 500 Internal Server Error)
What to Test:
Ensure correct status code for each API operation
Validate the full status line (HTTP/1.1 200 OK)
Proper error code and message for failure scenarios
The payload includes the actual data being sent or received. This can be in JSON, XML, or other formats.
What to Test:
Presence of all required fields
Correct data types and formats (e.g., integers, dates, strings)
Validation of optional and null values
Nested object structures or arrays
Encoding and parsing of special characters
A schema defines the expected structure and types of a response payload.
What to Test:
Field names and data types match the schema
Required fields are present
Optional fields are handled correctly
Use schema validation tools (e.g., JSON Schema Validator) to enforce rules
APIs should protect access using various auth mechanisms.
What to Test:
Valid and expired tokens
Missing or malformed credentials
Role-based access (admin vs. user)
Unauthorized access should be blocked with 401 or 403
Versioning ensures backward compatibility and smooth upgrades.
What to Test:
Correct behavior of /v1, /v2, etc.
Deprecation messages in older versions
Version headers or parameters if used
Pagination helps limit large data responses.
What to Test:
Page number and size parameters
Total record count, total pages
Navigation between pages
Empty pages and out-of-range values
APIs should respond gracefully and consistently to failures.
What to Test:
Proper HTTP status code (e.g., 400, 404, 500)
Descriptive error messages
Missing or invalid input handling
No sensitive data (e.g., stack traces) exposed in production errors
A well-tested API covers validations across:
HTTP headers
Status codes and response lines
Request and response payloads
Authentication and authorization
Versioning
Pagination
Error messages and fault tolerance
Schema compliance
These checks should be automated using tools like REST Assured with TestNG or JUnit for coverage and consistency. With thorough validation, you’ll catch issues early, improve stability, and ship better APIs.
When it comes to automating REST API tests in Java, REST Assured stands out as one of the most effective and developer-friendly libraries available. It simplifies HTTP request construction and response validation using a clean, fluent syntax—making it easy to write robust and readable test cases.
REST Assured is an open-source Java library built specifically for testing RESTful web services. It provides a domain-specific language (DSL) that makes it easier to perform API testing without writing verbose or boilerplate code.
Key capabilities include:
Support for common HTTP methods: GET, POST, PUT, DELETE, PATCH, HEAD, and OPTIONS
Validation of both JSON and XML payloads
DSL-based syntax for fluent and expressive test writing
Built-in support for authentication, cookies, headers, request parameters, and more
REST Assured is built on top of HTTP Builder and integrates well with popular Java testing frameworks like JUnit and TestNG.
When evaluating a test automation tool for REST APIs, a few features become essential: simplicity, flexibility, and support for modern API standards. REST Assured checks all the boxes.
Key Benefits:
Fluent DSL syntax: Makes test code readable and concise.
Powerful assertions: Supports response validation using JsonPath, XmlPath, and Hamcrest Matchers.
Seamless request setup: Easily configure headers, path/query parameters, body payloads, and authentication.
BDD-style test support: Write tests in Given-When-Then format, improving readability and maintainability.
Reusable specifications: Share base URIs, headers, and authentication setups across tests using RequestSpecification.
import static io.restassured.RestAssured.given;
import org.junit.Test;
public class HelloWorldTest {
@Test
public void verifyGoogleIsUp() {
given()
.when()
.get("http://www.google.com")
.then()
.statusCode(200);
}
}
This simple test performs a GET request to Google and asserts the response code is 200. REST Assured handles assertions internally—no need for explicit assertEquals.
REST Assured treats your REST API as a black box—tests are driven by HTTP/JSON interaction, irrespective of backend language or implementation.
Java project with a RESTful service endpoint
Maven or Gradle build system
Internet access to download dependencies
Basic knowledge of JUnit/TestNG and optionally Hamcrest
<dependency>
<groupId>com.jayway.restassured</groupId>
<artifactId>rest-assured</artifactId>
<version>2.1.0</version>
<scope>test</scope>
</dependency>
⚠️ Note: If you encounter conflicts (e.g., with Groovy or Jersey-Spring), you may need to exclude certain transitive dependencies and explicitly add compatible ones.
Use static imports from:
io.restassured.RestAssured.*
org.hamcrest.Matchers.*
For JSON Schema validation, import:
io.restassured.module.jsv.JsonSchemaValidator.*
To test Spring MVC controllers directly, use:
RestAssuredMockMvc.* (from the spring-mock-mvc module)
While REST Assured supports assertions out-of-the-box, combining it with TestNG enables powerful features like:
Data-driven testing (via @DataProvider)
Test grouping and parallel execution
Advanced reporting and configuration
You can still use JUnit, but TestNG enhances flexibility, especially for parameterized and reusable test logic.
Here’s what makes REST Assured a go-to choice for API testing:
BDD syntax (Given-When-Then)
Request Specification reuse to eliminate duplication
Groovy GPath for powerful JSON/XML parsing
Support for JSON Schema validation
Comprehensive header and cookie handling
Multi-part form testing
Authentication support (Basic, OAuth2, Digest, etc.)
SSL and certificate handling
Timeout management
Custom (De)Serializers for POJO mapping
REST Assured supports both simple and complex scenarios—from basic health checks to deeply nested response validation using Groovy expressions or Java lambdas.
Basic GET with assertions:
given().when().get("/users/1").then().statusCode(200);
POST with JSON payload:
given()
.contentType("application/json")
.body("{ \"name\": \"John\" }")
.when()
.post("/users")
.then()
.statusCode(201);
Reusable request specification:
RequestSpecification spec = new RequestSpecBuilder()
.setBaseUri("https://api.example.com")
.setContentType(ContentType.JSON)
.addHeader("Authorization", "Bearer token")
.build();
given().spec(spec).when().get("/data").then().statusCode(200);
🔚 Conclusion
REST Assured makes REST API testing in Java straightforward and expressive. Whether you're writing quick smoke tests or building a comprehensive automation suite, REST Assured provides everything you need—from clean syntax and schema validation to advanced configuration and custom serializers.
If you work in a Java-based test automation environment and need to validate APIs, REST Assured is the tool you should master.
When it comes to testing RESTful APIs in Java, REST Assured is one of the most widely adopted libraries. Its power lies in its fluent syntax, strong integration with Java testing frameworks, and rich feature set designed for both beginner and advanced automation engineers.
In this blog post, we’ll explore the core and advanced features of REST Assured—beyond the basics of GET, POST, and statusCode assertions. By the end, you’ll have a clear picture of how to fully leverage REST Assured for scalable, maintainable, and readable test automation.
REST Assured embraces Behavior Driven Development (BDD) with a clean and intuitive syntax:
given()
.baseUri("https://api.example.com")
.header("Accept", "application/json")
.when()
.get("/users/1")
.then()
.statusCode(200)
.body("name", equalTo("John"));
Benefits:
Clearly separates setup, execution, and assertions
Enhances test readability and maintainability
Aligns well with team collaboration and BDD principles
The RequestSpecification interface allows you to define common configuration once and reuse it across multiple tests:
RequestSpecification requestSpec = new RequestSpecBuilder()
.setBaseUri("https://api.example.com")
.setContentType(ContentType.JSON)
.addHeader("Authorization", "Bearer token123")
.build();
given().spec(requestSpec)
.when().get("/products")
.then().statusCode(200);
Benefits:
Avoids repetitive code for headers, base URIs, auth
Easier to maintain when common values change
Enables test modularity
REST Assured leverages Groovy GPath expressions to simplify parsing and validation of deeply nested or filtered JSON/XML responses.
given()
.when()
.get("/users")
.then()
.body("users.find { it.email == 'alex.smith@example.com' }.role", equalTo("admin"));
GPath in Action:
In this example, the test:
Queries a list of users returned by /users
Filters for the user with a specific email
Extracts the role field and asserts its value
GPath Capabilities Include:
find / findAll: Retrieve the first or all matching elements
collect: Transform elements into a new list
max, min: Identify elements based on numeric or comparable fields
Dot notation: Traverse deeply nested structures without verbose JSON parsing
Why it’s valuable: GPath removes the need to manually iterate over JSON nodes. It enables concise, expressive, and highly readable validations—even in large or dynamic response payloads.
REST Assured provides direct support for query and path parameters, essential for dynamic and data-driven testing:
given()
.queryParam("status", "active")
.pathParam("userId", 123)
.when()
.get("/users/{userId}")
.then()
.statusCode(200);
Technical Insights:
Easily simulate different search/filter scenarios
Supports both static and dynamic param values
REST Assured includes powerful logging methods to help you debug requests and responses:
given()
.log().all() // Logs request
.when()
.get("/orders")
.then()
.log().body(); // Logs response
Or log only on failure:
RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
Logging Options Include:
.log().headers()
.log().body()
.log().params()
.log().ifError()
.log().ifValidationFails()
REST Assured supports JSON Schema Validation using the json-schema-validator module:
given().when().get("/user/1")
.then().body(matchesJsonSchemaInClasspath("user-schema.json"));
Technical Insights:
Validates structure, types, required fields
Prevents breaking changes in API response
Works well in CI/CD environments
While JSON is the most common, REST Assured also supports XML parsing and assertions:
given()
.accept(ContentType.XML)
.when()
.get("/book/123")
.then()
.body("book.title", equalTo("Clean Code"));
Use XmlPath for more complex XML validations:
XmlPath xml = new XmlPath(response.asString());
String author = xml.get("book.author");
REST Assured’s tight integration with Groovy allows advanced querying and transformation. Alternatively, Java 8 lambdas can be used for complex assertions or stream filtering:
List<Integer> prices = response.jsonPath().getList("products.price");
int max = prices.stream().mapToInt(i -> i).max().orElse(0);
assertEquals(500, max);
Test APIs secured with:
Basic Authentication
Bearer Tokens
OAuth2
Digest Authentication
Client Certificates (SSL)
given()
.auth().preemptive().basic("user", "pass")
.when()
.get("/secure")
.then()
.statusCode(200);
Need to bypass SSL validation in test envs?
given().relaxedHTTPSValidation().get("/ssl-endpoint");
You can add, validate, and extract headers and cookies easily:
given()
.header("X-App-Version", "3.2.1")
.cookie("session_id", "xyz123")
.when()
.get("/dashboard")
.then()
.header("Content-Type", "application/json")
.cookie("session_id", notNullValue());
Simulate HTML form submissions using .formParam():
given()
.contentType("application/x-www-form-urlencoded")
.formParam("username", "admin")
.formParam("password", "pass123")
.when()
.post("/login")
.then()
.statusCode(200);
⏱ Configuring Timeouts in REST Assured
In API automation, it's important to prevent tests from hanging indefinitely due to slow or unresponsive services. REST Assured provides mechanisms to configure timeouts that help maintain test stability and responsiveness.
🔧 Types of Timeouts You Can Configure
Connection Timeout: The maximum time to wait while establishing a connection to the server.
Socket Timeout: The maximum time to wait for data after the connection has been established.
These settings ensure your tests fail fast when the server is unavailable or too slow, rather than stalling your entire test suite.
🛠 How to Set Timeouts in REST Assured
Handle slow or unresponsive APIs gracefully by setting timeouts:
Timeouts can be configured directly within the .given() clause using the HttpClientConfig:
given()
.config(RestAssured.config()
.httpClient(HttpClientConfig.httpClientConfig()
.setParam(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000) // 5 seconds
.setParam(CoreConnectionPNames.SO_TIMEOUT, 5000))) // 5 seconds
.when()
.get("/your-endpoint")
.then()
.statusCode(200);
In this example:
REST Assured waits up to 5 seconds to establish a connection.
Once connected, it waits up to 5 seconds to receive the response
REST Assured supports automatic JSON (de)serialization using libraries like Jackson or Gson. For more control over how data is converted between Java objects and JSON, you can register custom serializers and deserializers.
Use your POJOs directly by serializing/deserializing request/response bodies:
Serialize POJO:
User user = new User("John", "john@example.com");
given()
.contentType(ContentType.JSON)
.body(user)
.when()
.post("/users")
.then()
.statusCode(201);
Deserialize Response:
User createdUser = get("/users/1").as(User.class);
assertEquals("John", createdUser.getName());
Customize this with Jackson or Gson if you need specific serialization logic.
Why Custom (De)Serializers?
Sometimes, the out-of-the-box (de)serialization logic provided by libraries like Jackson or Gson doesn’t fit your specific needs. This could be due to complex data structures, a need for performance optimization, or the requirement to work with third-party classes that you cannot annotate directly. That’s where custom (de)serializers come into play.
Implementing Custom (De)Serialization with Jackson
Create Custom Serializer Class: Extend JsonSerializer<T> for serialization. Override the serialize method to implement your logic.
Create Custom Deserializer Class: Extend JsonDeserializer<T> for deserialization. Override the deserialize method to implement your logic.
Register Custom (De)Serializers: Use the SimpleModule class to register your custom (de)serializers with your ObjectMapper.
Here’s a high-level overview of what the code might look like:
Custom Serializer
public class CustomObjectSerializer extends JsonSerializer<CustomObject> {
@Override
public void serialize(CustomObject value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
// Implement serialization logic here
}
}
Custom Deserializer
public class CustomObjectDeserializer extends JsonDeserializer<CustomObject> {
@Override
public CustomObject deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
// Implement deserialization logic here
}
}
Registration
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(CustomObject.class, new CustomObjectSerializer());
module.addDeserializer(CustomObject.class, new CustomObjectDeserializer());
mapper.registerModule(module);
Using Custom (De)Serializers in REST Assured
REST Assured allows you to configure the ObjectMapper instance it uses, which means you can tell REST Assured to use your custom-configured ObjectMapper with your (de)serializers.
RestAssured.objectMapper(Type.JACKSON_2, mapper);
By doing this, REST Assured will utilize your custom (de)serialization logic for the specified object types, giving you full control over how objects are serialized to JSON for requests and deserialized from JSON for responses.
Example: Registering a Custom Jackson Deserializer
public class CustomUserDeserializer extends JsonDeserializer<User> {
@Override
public User deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
JsonNode node = p.getCodec().readTree(p);
String fullName = node.get("firstName").asText() + " " + node.get("lastName").asText();
return new User(fullName, node.get("email").asText());
}
}
// Register with ObjectMapper
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(User.class, new CustomUserDeserializer());
mapper.registerModule(module);
// Apply in REST Assured
RestAssured.objectMapper(new Jackson2ObjectMapperFactory() {
public ObjectMapper create(Class cls, String charset) {
return mapper;
}
});
REST Assured isn't just a lightweight HTTP client—it's a full-featured API testing framework purpose-built for Java teams.
Core Highlights:
✅ Fluent BDD-style syntax
📦 Reusable request specifications
🧬 Powerful JSON/XML parsing with GPath
🔐 Built-in auth and SSL testing
📄 Schema validation
🧰 Logging, debugging, timeouts, and more
If you're building a test automation framework for REST APIs, REST Assured should be one of your go-to tools—especially in Java environments. With its flexibility, rich feature set, and strong community, it scales well from smoke tests to complex regression suites.
Looking to go even further? Combine REST Assured with:
TestNG or JUnit for test lifecycle management
Allure Reports for beautiful test reporting
CI tools like Jenkins or GitHub Actions for automation