API testing has become a fundamental part of modern software development. As applications increasingly rely on RESTful services, developers and QA engineers need efficient ways to validate APIs quickly and accurately. Among the various HTTP methods used in REST APIs, the PATCH method is especially important because it allows partial updates to resources instead of replacing the entire object.
When performing API automation in Java, REST Assured is one of the most widely used frameworks because of its simplicity, readability, and seamless integration with testing tools like JUnit and TestNG. Testing PATCH requests using REST Assured helps ensure that APIs correctly update only the intended fields while maintaining data integrity.
This article provides a detailed explanation of how to test PATCH requests using REST Assured in Java, including setup instructions, coding examples, validation techniques, best practices, and common pitfalls.
Understanding PATCH Requests in REST APIs
Before diving into implementation, it is important to understand what PATCH requests are and how they differ from PUT requests.
A PATCH request updates only specific fields of an existing resource. Unlike PUT, which replaces the complete object, PATCH modifies only the supplied attributes.
For example, consider the following user object:
{
"id": 101,
"name": "John",
"email": "john@example.com",
"status": "active"
}
If you want to update only the status field, a PATCH request would send:
{
"status": "inactive"
}
The remaining fields remain unchanged.
PATCH requests are commonly used for:
- Updating user profiles
- Changing account status
- Editing configuration settings
- Updating order states
- Modifying partial resource data
Because PATCH operations affect only selective fields, testing them properly is extremely important.
What Is REST Assured?
REST Assured is a Java-based library designed for testing RESTful APIs. It simplifies HTTP request handling and response validation using a clean and expressive syntax.
Key benefits include:
- Easy API request creation
- JSON and XML validation support
- Integration with JUnit and TestNG
- Authentication support
- Schema validation
- Logging and debugging features
REST Assured follows a Behavior Driven Development (BDD) style using:
given()
when()
then()
This makes test cases highly readable and maintainable.
Setting Up REST Assured in Java
To begin testing PATCH requests, you first need to configure REST Assured in your Java project.
Maven Dependency
Add the following dependency to your pom.xml file:
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>5.4.0</version>
<scope>test</scope>
</dependency>
For TestNG support:
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.8.0</version>
<scope>test</scope>
</dependency>
For JUnit:
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
Basic Structure of a PATCH Request in REST Assured
A PATCH request in REST Assured generally follows this structure:
given()
.header("Content-Type", "application/json")
.body(requestPayload)
.when()
.patch("/users/101")
.then()
.statusCode(200);
The steps are:
- Define request headers and body
- Send PATCH request
- Validate response
Simple PATCH Request Example
Let us start with a simple example.
Suppose the API endpoint is:
https://reqres.in/api/users/2
We want to update the user’s job title.
Example Code
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
public class PatchRequestTest {
@Test
public void updateUserJob() {
String requestBody = "{\n" +
" \"job\": \"Senior QA Engineer\"\n" +
"}";
given()
.baseUri("https://reqres.in")
.contentType(ContentType.JSON)
.body(requestBody)
.when()
.patch("/api/users/2")
.then()
.statusCode(200)
.body("job", equalTo("Senior QA Engineer"))
.log().all();
}
}
Explanation of the Code
Let us break down the code step-by-step.
Base URI
.baseUri("https://reqres.in")
Defines the server URL.
Content Type
.contentType(ContentType.JSON)
Specifies that the request body is JSON.
Request Body
.body(requestBody)
Contains the fields to update.
PATCH Method
.patch("/api/users/2")
Sends the PATCH request.
Response Validation
.statusCode(200)
.body("job", equalTo("Senior QA Engineer"))
Verifies that:
- Status code is correct
- Response body contains updated value
Using HashMap for Dynamic PATCH Payloads
Instead of manually writing JSON strings, you can use a HashMap.
Example
import java.util.HashMap;
import java.util.Map;
@Test
public void patchUsingHashMap() {
Map<String, Object> payload = new HashMap<>();
payload.put("job", "Automation Architect");
given()
.baseUri("https://reqres.in")
.contentType(ContentType.JSON)
.body(payload)
.when()
.patch("/api/users/2")
.then()
.statusCode(200)
.body("job", equalTo("Automation Architect"));
}
This approach is cleaner and easier to maintain.
Validating Response Headers
PATCH response validation should also include headers.
Example
@Test
public void validateHeaders() {
String payload = "{ \"job\": \"DevOps Engineer\" }";
given()
.baseUri("https://reqres.in")
.contentType(ContentType.JSON)
.body(payload)
.when()
.patch("/api/users/2")
.then()
.statusCode(200)
.header("Content-Type", containsString("application/json"));
}
Header validation ensures API compliance.
Extracting Response Data
Sometimes you need to extract response values for further validation.
Example
import io.restassured.response.Response;
@Test
public void extractPatchResponse() {
String payload = "{ \"job\": \"Backend Developer\" }";
Response response = given()
.baseUri("https://reqres.in")
.contentType(ContentType.JSON)
.body(payload)
.when()
.patch("/api/users/2");
String updatedJob = response.jsonPath().getString("job");
System.out.println("Updated Job: " + updatedJob);
}
This is useful for chained API validations.
Using POJO Classes for PATCH Requests
For enterprise-level automation frameworks, using POJO classes is recommended.
Create Request POJO
public class PatchRequest {
private String job;
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
}
Test Class
@Test
public void patchUsingPojo() {
PatchRequest request = new PatchRequest();
request.setJob("Tech Lead");
given()
.baseUri("https://reqres.in")
.contentType(ContentType.JSON)
.body(request)
.when()
.patch("/api/users/2")
.then()
.statusCode(200)
.body("job", equalTo("Tech Lead"));
}
POJO-based payload handling improves maintainability and readability.
Testing Authentication with PATCH Requests
Many APIs require authentication tokens.
Example Using Bearer Token
@Test
public void patchWithAuthToken() {
String token = "your_access_token";
String payload = "{ \"status\": \"inactive\" }";
given()
.baseUri("https://api.example.com")
.header("Authorization", "Bearer " + token)
.contentType(ContentType.JSON)
.body(payload)
.when()
.patch("/users/101")
.then()
.statusCode(200);
}
Authentication testing is critical for secure APIs.
Sending PATCH Requests with Path Parameters
REST Assured supports dynamic path parameters.
Example
@Test
public void patchUsingPathParam() {
String payload = "{ \"job\": \"Manager\" }";
given()
.baseUri("https://reqres.in")
.pathParam("userId", 2)
.contentType(ContentType.JSON)
.body(payload)
.when()
.patch("/api/users/{userId}")
.then()
.statusCode(200);
}
This approach improves flexibility.
Sending PATCH Requests with Query Parameters
Some APIs use query parameters alongside PATCH requests.
Example
@Test
public void patchWithQueryParam() {
String payload = "{ \"role\": \"admin\" }";
given()
.baseUri("https://api.example.com")
.queryParam("notify", true)
.contentType(ContentType.JSON)
.body(payload)
.when()
.patch("/users/10")
.then()
.statusCode(200);
}
Negative Testing for PATCH Requests
Negative testing ensures the API behaves correctly under invalid conditions.
Invalid Endpoint Example
@Test
public void patchInvalidEndpoint() {
String payload = "{ \"job\": \"Tester\" }";
given()
.baseUri("https://reqres.in")
.contentType(ContentType.JSON)
.body(payload)
.when()
.patch("/api/unknown")
.then()
.statusCode(404);
}
Testing Invalid Payloads
Example
@Test
public void patchInvalidPayload() {
String payload = "{ invalid json }";
given()
.baseUri("https://reqres.in")
.contentType(ContentType.JSON)
.body(payload)
.when()
.patch("/api/users/2")
.then()
.statusCode(400);
}
Negative scenarios improve API robustness.
Logging Requests and Responses
Logging is useful for debugging failed tests.
Example
@Test
public void patchWithLogging() {
String payload = "{ \"job\": \"Architect\" }";
given()
.baseUri("https://reqres.in")
.contentType(ContentType.JSON)
.body(payload)
.log().all()
.when()
.patch("/api/users/2")
.then()
.log().all()
.statusCode(200);
}
Logs help identify issues quickly.
Using Specifications in REST Assured
Request specifications reduce code duplication.
Example
import io.restassured.specification.RequestSpecification;
@Test
public void patchUsingSpecification() {
RequestSpecification requestSpec = given()
.baseUri("https://reqres.in")
.contentType(ContentType.JSON);
String payload = "{ \"job\": \"Director\" }";
requestSpec
.body(payload)
.when()
.patch("/api/users/2")
.then()
.statusCode(200);
}
Specifications improve framework scalability.
Validating JSON Schema for PATCH Responses
Schema validation ensures response structure consistency.
Example
@Test
public void validatePatchSchema() {
String payload = "{ \"job\": \"Consultant\" }";
given()
.baseUri("https://reqres.in")
.contentType(ContentType.JSON)
.body(payload)
.when()
.patch("/api/users/2")
.then()
.statusCode(200)
.body(matchesJsonSchemaInClasspath("patch-schema.json"));
}
Schema validation prevents unexpected response changes.
Integrating PATCH Tests with TestNG
REST Assured works well with TestNG.
Example
import org.testng.annotations.Test;
public class PatchTestNG {
@Test
public void updateUser() {
String payload = "{ \"job\": \"QA Lead\" }";
given()
.baseUri("https://reqres.in")
.contentType(ContentType.JSON)
.body(payload)
.when()
.patch("/api/users/2")
.then()
.statusCode(200);
}
}
TestNG provides reporting and parallel execution support.
Common Challenges While Testing PATCH Requests
API testers often encounter several issues while testing PATCH endpoints.
Partial Update Validation
Ensure only specified fields are updated.
Incorrect Content Types
Some APIs require:
application/json-patch+json
instead of:
application/json
Authentication Failures
Expired or invalid tokens can cause unauthorized responses.
Inconsistent API Behavior
Some APIs incorrectly implement PATCH as PUT.
Serialization Issues
Improper payload serialization may break requests.
Best Practices for PATCH Request Testing
Following best practices improves reliability and maintainability.
Use Reusable Methods
Create helper methods for common operations.
Validate Both Positive and Negative Scenarios
Always test valid and invalid requests.
Use Environment Variables
Avoid hardcoding URLs and tokens.
Implement Logging
Logs simplify debugging.
Validate Response Time
Performance matters for APIs.
Example:
.then()
.time(lessThan(3000L));
Use POJO Serialization
POJOs improve code organization.
Add Assertions for Data Integrity
Verify that non-updated fields remain unchanged.
Real-World PATCH Testing Scenario
Consider an e-commerce application where order status needs updating.
Example Payload
{
"status": "Shipped"
}
REST Assured Test
@Test
public void updateOrderStatus() {
String payload = "{ \"status\": \"Shipped\" }";
given()
.baseUri("https://api.shop.com")
.header("Authorization", "Bearer token")
.contentType(ContentType.JSON)
.body(payload)
.when()
.patch("/orders/5001")
.then()
.statusCode(200)
.body("status", equalTo("Shipped"));
}
This type of scenario is common in production-grade systems.
Difference Between PUT and PATCH Testing
| Feature | PUT | PATCH |
|---|---|---|
| Updates | Entire resource | Partial resource |
| Payload Size | Larger | Smaller |
| Risk of Data Loss | Higher | Lower |
| Usage | Full replacement | Partial modification |
| Testing Focus | Entire object validation | Selective field validation |
Understanding this distinction is important during API automation.
Advanced Validation Techniques
Response Time Validation
.then()
.time(lessThan(2000L));
Content Validation
.body("updatedAt", notNullValue());
Multiple Assertions
.then()
.statusCode(200)
.body("job", equalTo("Engineer"))
.body("updatedAt", notNullValue());
Combining assertions increases test reliability.
Building a Robust API Automation Framework
PATCH request testing is usually part of a larger framework.
A scalable framework typically includes:
- Base test classes
- Utility methods
- Request specifications
- Response validators
- Logging utilities
- Data-driven testing
- Reporting integration
- CI/CD pipeline integration
REST Assured integrates well with:
- Jenkins
- Maven
- Allure Reports
- Extent Reports
- GitHub Actions
This makes it ideal for enterprise API automation.
Conclusion
Testing PATCH requests using REST Assured in Java is an essential skill for modern API testers and automation engineers. Since PATCH operations are designed for partial updates, validating them carefully ensures APIs behave correctly without unintentionally modifying unrelated data.
REST Assured simplifies PATCH request testing through its expressive syntax, powerful validation capabilities, and seamless Java integration. From basic PATCH requests to advanced scenarios involving authentication, path parameters, schema validation, logging, and reusable frameworks, REST Assured provides everything needed for comprehensive API testing.
A successful PATCH testing strategy should include positive validation, negative testing, response verification, schema validation, performance checks, and authentication handling. Using best practices such as POJO serialization, reusable request specifications, proper assertions, and logging can significantly improve test reliability and maintainability.
In real-world enterprise applications, PATCH requests are heavily used for updating user profiles, order statuses, account settings, permissions, and many other partial modifications. Poorly tested PATCH endpoints can lead to data corruption, inconsistent application states, and serious production issues. Therefore, investing time in designing robust PATCH API tests is extremely valuable.
By mastering REST Assured PATCH request testing, QA engineers and developers can build scalable, maintainable, and highly reliable API automation frameworks that support continuous integration and modern agile development workflows.