Negative Testing in REST Assured

Negative testing verifies how an API behaves when it receives invalid, unexpected, or malformed input.

The objective is to ensure that the API handles invalid requests gracefully by returning:

  • Appropriate HTTP status codes
  • Meaningful error messages
  • A consistent error response structure

Instead of crashing or exposing sensitive information.

Think of it like an ATM rejecting an incorrect PIN. It should reject the request with a clear message rather than malfunction.


Advertisement

Interview Answer

"Negative testing in API automation means sending invalid or unexpected inputs to verify that the API returns appropriate error responses. Using REST Assured, I validate status codes such as 400, 401, 403, 404, 405, and 500, along with meaningful error messages and the error response schema to ensure the API is secure, stable, and follows the API contract."


Why is Negative Testing Important?

Positive testing verifies that the API works correctly with valid inputs.

Negative testing verifies that the API behaves correctly when users provide invalid or unexpected input.

It ensures that the application:

  • Rejects invalid requests
  • Returns appropriate HTTP status codes
  • Provides meaningful error messages
  • Does not expose sensitive information
  • Remains stable under invalid or malicious input

Negative Testing Flow

Client Request
      │
      ▼
Invalid Input
      │
      ▼
API Validation
      │
      ▼
Error Response
      │
      ▼
Validate
• Status Code
• Error Message
• Error Schema

Common Negative Test Scenarios

Scenario Expected Status Code
Missing mandatory field 400 Bad Request
Invalid data type 400 Bad Request
Invalid email format 400 Bad Request
Empty request body 400 Bad Request
Invalid authentication token 401 Unauthorized
Missing authentication token 401 Unauthorized
Insufficient permissions 403 Forbidden
Invalid endpoint 404 Not Found
Wrong HTTP method 405 Method Not Allowed
Unsupported Content-Type (e.g. text/plain) 415 Unsupported Media Type
Valid format but breaks a business rule 422 Unprocessable Entity (or 400)
Duplicate resource (email already registered) 409 Conflict
Too many requests 429 Too Many Requests

Common Negative Test Cases


1. Missing Mandatory Fields

Request

{
  "email": "john@test.com"
}

Missing field:

name

Expected Response

400 Bad Request

2. Invalid Data Type

Expected

{
  "age": 25
}

Actual

{
  "age": "twenty-five"
}

Expected Response

400 Bad Request

3. Invalid Email Format

Request

{
   "email":"abc.com"
}

Expected Response

400 Bad Request

4. Empty Request Body

Request

{}

Expected Response

400 Bad Request

5. Invalid JWT Token

Request Header

Authorization: Bearer InvalidToken123

Expected Response

401 Unauthorized

6. Missing Authorization Header

No authentication header is provided.

Expected Response

401 Unauthorized

7. Wrong Endpoint

Request

/userss

Expected Response

404 Not Found

8. Wrong HTTP Method

Instead of

GET

the client sends

DELETE

Expected Response

405 Method Not Allowed

9. A 500 Is Never the Expected Result

If invalid input produces 500 Internal Server Error, the negative test has found a bug: the server failed to validate the input and crashed instead of returning a 4xx with a clear message. Write negative tests to expect the correct 4xx code, so a 500 fails the test and gets reported — and check that the error body doesn't leak stack traces, SQL or internal class names.

.then()
    .statusCode(both(greaterThanOrEqualTo(400)).and(lessThan(500)))     // any 4xx — never 5xx
    .body(not(containsString("Exception")))
    .body(not(containsString("at com.")));

REST Assured Example

The following example validates an invalid request.

@DataProvider(name = "invalidUsers")
public Object[][] invalidUsers() {
    return new Object[][] {
        { "{}",                                             400, "name is required"     },
        { "{\"name\":\"John\",\"age\":\"twenty-five\"}",   400, "age must be a number" },
        { "{\"name\":\"John\",\"email\":\"abc.com\"}",     400, "email is invalid"     },
        { "{\"name\":\"John\",",                          400, "malformed JSON"       },
    };
}

@Test(dataProvider = "invalidUsers")
public void createUserRejectsInvalidInput(String payload, int expectedStatus, String expectedMessage) {
    given()
        .spec(authSpec)
        .contentType(ContentType.JSON)
        .body(payload)
    .when()
        .post("/users")
    .then()
        .statusCode(expectedStatus)
        .body("errorMessage", containsStringIgnoringCase(expectedMessage))
        .body(matchesJsonSchemaInClasspath("schemas/error_schema.json"));
}

One data-driven test covers many invalid inputs, and each row checks status, message and error schema together. Adjust the expected messages to your API's contract. For boundary values (minimum and maximum lengths, 0, negative and very large numbers), add rows rather than new test methods.


Negative Testing Workflow

Prepare Invalid Request
        │
        ▼
Send API Request
        │
        ▼
Receive Error Response
        │
        ▼
Validate Status Code
        │
        ▼
Validate Error Message
        │
        ▼
Validate Error Schema

Real-Time Example

In one project, I intentionally sent a POST request with an empty request body and an invalid email format. The API correctly returned 400 Bad Request along with a meaningful error message. I validated both the response body and the error response schema to ensure the API handled invalid input consistently.


Best Practices

  • Validate both positive and negative scenarios.
  • Never validate only the HTTP status code.
  • Verify meaningful error messages.
  • Validate the error response schema.
  • Test authentication failures.
  • Test authorization failures.
  • Test invalid request payloads.
  • Verify incorrect endpoints and HTTP methods.
  • Ensure APIs never expose sensitive information in error responses.

📚 Official documentation: REST Assured official site · MDN: HTTP

Frequently Asked Questions (FAQs)

1. What is negative testing in API automation?

Negative testing involves sending invalid, unexpected, or malformed inputs to verify that the API rejects them gracefully by returning appropriate error status codes, meaningful error messages, and a consistent error response structure.


2. What are common negative test scenarios?

Common negative scenarios include:

  • Missing mandatory fields
  • Invalid data types
  • Invalid email formats
  • Empty request body
  • Invalid or expired authentication tokens
  • Missing authentication headers
  • Wrong endpoint
  • Wrong HTTP method
  • Internal server errors

The expected HTTP status codes typically include:

  • 400 Bad Request
  • 401 Unauthorized
  • 403 Forbidden
  • 404 Not Found
  • 405 Method Not Allowed
  • 500 Internal Server Error

3. Why is negative testing important?

Negative testing ensures that APIs handle invalid requests safely by:

  • Returning correct error responses
  • Preventing application crashes
  • Protecting sensitive information
  • Ensuring consistent API behavior
  • Improving application reliability

Validating Error Messages

Validating error messages means verifying that the API returns a meaningful, accurate, and contract-compliant error message whenever a request fails.

Checking only the HTTP status code is not enough. A response may return the correct status code but still contain an incorrect or misleading error message.

A robust API test should validate:

  • HTTP status code
  • Error message
  • Error code (if available)
  • Error response schema

Interview Answer

"Along with validating the HTTP status code, I also validate the error message returned by the API. This ensures that the API provides meaningful, consistent, and contract-compliant error information, making it easier for clients to handle errors and developers to debug issues."


Why Validate Error Messages?

Validating error messages ensures that they are:

  • Meaningful
  • User-friendly
  • Consistent
  • Helpful for debugging
  • Defined by the API contract

Sample Error Response

{
  "errorCode": "USR001",
  "errorMessage": "Email is required"
}

REST Assured Example

given()

.when()
        .post("/users")

.then()
        .statusCode(400)
        .body("errorMessage",
              equalTo("Email is required"));

What Should Be Validated?

A typical error response may include:

  • Error Code
  • Error Message
  • Timestamp
  • HTTP Status
  • Request Path

Example:

{
  "errorCode": "USR001",
  "errorMessage": "Email is required",
  "timestamp": "2026-07-12T10:30:45Z",
  "status": 400,
  "path": "/users"
}

Error Validation Flow

Invalid Request
       │
       ▼
Receive Error Response
       │
       ▼
Validate Status Code
       │
       ▼
Validate Error Code
       │
       ▼
Validate Error Message

Real-Time Example

In one project, when the email field was missing, the API correctly returned 400 Bad Request along with the message "Email is required". We validated both the status code and the exact error message to ensure the API returned meaningful feedback.


Best Practices

  • Validate both status code and error message.
  • Verify business-specific error codes.
  • Ensure messages are meaningful and consistent.
  • Avoid validating only partial responses.
  • Compare responses with the API documentation or contract.

Validating Error Response Schema

Error responses should follow a predefined API contract, just like successful responses.

Instead of validating only individual fields, validate the entire error response structure using JSON Schema Validation.


Interview Answer

"In addition to validating the status code and error message, I validate the complete error response schema using JSON Schema Validation. This ensures that all required fields, data types, and the overall response structure comply with the API contract."


Sample Error Response

{
  "errorCode": "USR001",
  "errorMessage": "Email is required",
  "timestamp": "2026-07-12T10:30:45Z"
}

Sample JSON Schema

{
  "$schema": "http://json-schema.org/draft-07/schema#",

  "type": "object",

  "properties": {

    "errorCode": {
      "type": "string"
    },

    "errorMessage": {
      "type": "string"
    },

    "timestamp": {
      "type": "string"
    }

  },

  "required": [
    "errorCode",
    "errorMessage",
    "timestamp"
  ]
}

Schema Validation in REST Assured

response.then()
        .statusCode(400)
        .body(matchesJsonSchemaInClasspath(
                "schemas/error_schema.json"));

What Does Error Schema Validation Check?

JSON Schema Validation verifies:

  • Response structure
  • Required fields
  • Optional fields
  • Data types
  • Nested objects
  • Arrays
  • Overall API contract

Error Schema Validation Flow

Error Response
       │
       ▼
JSON Schema
       │
       ▼
Validate
│
├── Structure
├── Required Fields
├── Data Types
├── Arrays
└── Nested Objects

Error Schema Validation Scenarios

Scenario Expected Status Code Schema File
Missing mandatory field 400 error_schema.json
Invalid authentication 401 error_schema.json
Forbidden access 403 error_schema.json
Invalid endpoint 404 error_schema.json
Invalid HTTP method 405 error_schema.json
Internal server error 500 error_schema.json

Why Validate the Error Schema?

Schema validation provides several benefits:

  • Consistent error responses
  • Predictable API behavior
  • Better client integration
  • Easier debugging
  • Reduced downstream failures
  • API contract compliance

Real-Time Example

During one project, every negative API scenario—including invalid authentication, missing mandatory fields, and invalid endpoints—was validated against a common error_schema.json file. This ensured that every error response followed the same contract, making it easier for frontend applications and downstream services to process errors consistently.


Error Response Validation Workflow

Invalid Request
       │
       ▼
Receive Error Response
       │
       ▼
Validate Status Code
       │
       ▼
Validate Error Message
       │
       ▼
Validate Error Schema
       │
       ▼
Test Passed

Best Practices

  • Validate the HTTP status code first.
  • Validate business-specific error codes.
  • Validate meaningful error messages.
  • Validate the complete JSON Schema.
  • Store schema files under src/test/resources/schemas.
  • Reuse the same schema for similar error responses.
  • Keep schema files updated whenever the API contract changes.
  • Validate both positive and negative response schemas.

Frequently Asked Questions (FAQs)

1. How do you validate error messages?

I validate both the HTTP status code and the errorMessage field in the response body using REST Assured assertions. This ensures that the API returns meaningful, accurate, and contract-compliant error information.

Example:

.body("errorMessage", equalTo("Email is required"))

2. Why is validating the error message important?

Validating the error message ensures that the API:

  • Provides meaningful feedback
  • Helps users understand the issue
  • Assists developers during debugging
  • Maintains consistency across all error responses
  • Follows the API contract

3. What is an error response schema?

An error response schema is a JSON Schema that defines the expected structure of an error response, including required fields, optional fields, data types, nested objects, and arrays.


4. How do you validate the error response schema?

I create an error_schema.json file and validate the response using REST Assured's JSON Schema Validator.

Example:

.body(matchesJsonSchemaInClasspath(
        "schemas/error_schema.json"))

The test fails if:

  • Required fields are missing
  • Unexpected fields are present
  • Data types do not match
  • The overall response structure differs from the schema

5. What does JSON Schema validation verify?

JSON Schema validation checks:

  • Response structure
  • Required fields
  • Optional fields
  • Data types
  • Nested objects
  • Arrays
  • Overall API contract compliance

6. Why should error responses also follow a schema?

Validating error response schemas ensures:

  • Consistent API behavior
  • Predictable responses for client applications
  • Easier integration with frontend and downstream services
  • Better debugging
  • Early detection of contract-breaking changes
  • Improved maintainability of the API automation framework

Handling API Failures

API failures can occur due to various reasons, including invalid requests, server-side issues, network problems, timeouts, incorrect configurations, or unexpected responses.

A well-designed automation framework should be able to:

  • Detect failures
  • Capture complete logs
  • Analyze the root cause
  • Retry temporary failures
  • Report failures with meaningful information

Interview Answer

"In our API automation framework, whenever an API fails, we capture the complete request and response details, analyze the status code and response body, handle unexpected exceptions using try-catch blocks, and retry only transient failures such as network issues or server timeouts. If the failure persists, the test fails with detailed logs to help developers identify the root cause quickly."


Common Causes of API Failures

API failures may occur because of:

  • Invalid requests
  • Server downtime
  • Network issues
  • Timeout errors
  • Incorrect configuration
  • Invalid authentication
  • Unexpected server responses
  • Temporary infrastructure failures

API Failure Handling Workflow

API Request
      │
      ▼
Request Fails
      │
      ▼
Capture Request & Response Logs
      │
      ▼
Analyze Status Code
      │
      ▼
Identify Root Cause
      │
      ▼
Retry (Transient Errors Only)
      │
      ▼
Still Failed?
      │
      ▼
Fail Test with Detailed Logs

Best Practices for Handling API Failures

1. Capture Complete Request and Response Logs

Whenever an API fails, log all relevant details.

Capture:

  • Request URL
  • HTTP Method
  • Headers
  • Query Parameters
  • Path Parameters
  • Request Body
  • Response Body
  • Status Code
  • Response Time

Complete logs make debugging significantly easier.


2. Analyze HTTP Status Codes

The status code often provides the first clue about the failure.

Status Code Meaning
400 Bad Request
401 Unauthorized
403 Forbidden
404 Resource Not Found
405 Method Not Allowed
500 Internal Server Error
503 Service Unavailable

Understanding the status code helps identify whether the issue is with the request, authentication, authorization, or the server itself.


3. Handle Exceptions

When a call throws before any response arrives (connection refused, timeout), capture enough context to debug it — but still let the test fail.

REST Assured Example

Response response;
try {
    response = given().spec(authSpec).get("/users");
} catch (Exception e) {
    log.error("GET /users failed before a response arrived: {}", e.toString());
    throw e;                                              // re-throw: the test must still fail
}
response.then().statusCode(200);

Never swallow the exception. A catch block that only logs turns a broken call into a passing test. Log useful context, then re-throw (or let it propagate) so the failure is reported. Most of the time you don't need try/catch at all — REST Assured's log().ifValidationFails() plus a TestNG listener gives the same evidence. See Logging & Response Extraction.


Why Use Exception Handling?

Exception handling helps:

  • Prevent framework crashes
  • Capture meaningful error information
  • Improve debugging
  • Continue execution where appropriate
  • Generate cleaner reports

4. Retry Temporary Failures

Retry only when failures are temporary.

Examples include:

  • Network interruptions
  • Timeout errors
  • Temporary server overload
  • 503 Service Unavailable
  • Intermittent connectivity issues

Do not retry genuine application defects.


Real-Time Example

In our framework, every API failure captures the complete request and response details. If a temporary network issue occurs, the framework retries the request a limited number of times. If the issue still exists, the test fails with detailed logs, making it easier for developers to identify and resolve the root cause.


Retrying Failed API Calls

Retrying means automatically executing the same API request again when the failure is temporary.

This helps reduce flaky test failures caused by unstable infrastructure.


Interview Answer

"Our framework retries only transient failures such as network issues, timeout errors, or temporary server failures. We never retry functional failures because that could hide genuine application defects."


When Should You Retry?

Retry for:

  • Network failures
  • Timeout errors
  • Temporary server failures
  • 503 Service Unavailable
  • Intermittent connectivity issues
  • Temporary infrastructure problems

When Should You NOT Retry?

Do not retry:

  • 400 Bad Request
  • 401 Unauthorized
  • 403 Forbidden
  • Business validation failures
  • Functional defects
  • Incorrect API implementation

Retrying these failures only wastes execution time and may hide genuine defects.


Retry Decision Flow

API Failure
      │
      ▼
Temporary Failure?
      │
 ┌────┴────┐
 │         │
Yes        No
 │          │
 ▼          ▼
Retry     Fail Immediately

Retry Using a Java Loop

A simple retry mechanism can be implemented using a loop.

static Response withRetry(Supplier<Response> call, int maxAttempts) throws InterruptedException {
    Response response = null;
    for (int attempt = 1; attempt <= maxAttempts; attempt++) {
        try {
            response = call.get();
            if (response.statusCode() < 500) return response;       // 2xx/4xx are real results — don't retry
            log.warn("Attempt {} returned {}", attempt, response.statusCode());
        } catch (RuntimeException e) {                             // connection reset, timeout
            if (attempt == maxAttempts) throw e;
            log.warn("Attempt {} failed: {}", attempt, e.toString());
        }
        if (attempt < maxAttempts) Thread.sleep(1000L * attempt);  // back off
    }
    return response;
}

Response res = withRetry(() -> given().spec(authSpec).get("/users"), 3);
res.then().statusCode(200);                                        // the assertion still decides

Unlike a simple "loop until 200" — which also retries 4xx responses that signal real defects, has no pause, and never fails the test — this retries only server and connection errors, backs off, logs every attempt, and leaves the final assertion to the test. The logic was verified with simulated responses in REST Assured Real-Time Scenarios.


Retry Flow

Attempt 1
     │
     ▼
Success?
 │
 ├── Yes → Continue
 │
 └── No
      │
      ▼
Attempt 2
      │
      ▼
Success?
 │
 ├── Yes
 │
 └── No
      │
      ▼
Attempt 3
      │
      ▼
Still Failed?
      │
      ▼
Fail Test

Retry Using TestNG Retry Analyzer

Large automation frameworks generally use TestNG's IRetryAnalyzer instead of writing retry logic in every test.

The Retry Analyzer automatically reruns failed test cases.


Advantages of Retry Analyzer

  • Centralized retry logic
  • Cleaner test cases
  • Easy framework maintenance
  • No duplicate retry code
  • Better CI/CD integration

Retry Strategy

API Request
      │
      ▼
Failed?
      │
      ▼
Retry 1
      │
      ▼
Retry 2
      │
      ▼
Retry 3
      │
      ▼
Still Failed?
      │
      ▼
Mark Test Failed

Retry Comparison

Java Loop TestNG Retry Analyzer
Implemented inside test code Framework-level implementation
Repeated in multiple tests Centralized
Harder to maintain Easier to maintain
Less scalable Highly scalable

Logging During Retry

Each retry attempt should be logged.

Example log:

Attempt 1 Failed
Retrying...

Attempt 2 Failed
Retrying...

Attempt 3 Failed

Maximum retry count reached.

Test Failed.

Proper logging makes debugging much easier.


Real-Time Example

In our regression framework, temporary 503 Service Unavailable responses occasionally occurred due to server maintenance. The Retry Analyzer automatically retried the request twice. If the API recovered, the test continued successfully; otherwise, the execution failed with complete request and response logs for investigation.


Best Practices

  • Retry only transient failures.
  • Limit retries to 2–3 attempts.
  • Log every retry attempt.
  • Never retry functional failures.
  • Capture complete request and response logs.
  • Validate status code before retrying.
  • Fail fast for genuine application defects.
  • Use TestNG's IRetryAnalyzer for large automation frameworks.

Failure Handling Workflow

API Request
      │
      ▼
Receive Response
      │
      ▼
Status Code
      │
      ▼
Success?
 │
 ├── Yes
 │      │
 │      ▼
 │   Continue
 │
 └── No
        │
        ▼
Capture Logs
        │
        ▼
Temporary Failure?
 │
 ├── Yes
 │      │
 │      ▼
 │    Retry
 │
 └── No
        │
        ▼
Fail Test

Frequently Asked Questions (FAQs)

1. How do you handle API failures?

I capture the complete request and response details, analyze the HTTP status code and response body, handle unexpected exceptions using try-catch blocks, and retry only temporary failures. If the problem persists, the test fails with detailed logs that help developers identify the root cause.


2. Why is logging important during API failures?

Logging captures:

  • Request URL
  • HTTP Method
  • Headers
  • Parameters
  • Request Body
  • Response Body
  • Status Code
  • Response Time

These details significantly reduce debugging time and help identify the exact cause of failures.


3. Which HTTP status codes are commonly analyzed during failures?

The most common status codes are:

  • 400 Bad Request
  • 401 Unauthorized
  • 403 Forbidden
  • 404 Not Found
  • 405 Method Not Allowed
  • 500 Internal Server Error
  • 503 Service Unavailable

Each status code helps determine the nature of the failure.


4. When should API requests be retried?

Retries should be performed only for temporary issues such as:

  • Network failures
  • Timeout errors
  • Temporary server overload
  • 503 Service Unavailable
  • Intermittent connectivity problems

Retries should not be performed for functional defects or business validation failures.


5. How do you retry failed API calls?

There are two common approaches:

  • A Java retry loop with a maximum retry count.
  • TestNG's IRetryAnalyzer, which automatically retries failed test cases at the framework level.

For enterprise automation frameworks, IRetryAnalyzer is generally preferred because it centralizes retry logic and improves maintainability.


6. Why shouldn't functional failures be retried?

Functional failures such as 400 Bad Request, 401 Unauthorized, business validation failures, or incorrect application behavior indicate genuine defects. Retrying these requests wastes execution time and may hide real issues that should be reported to developers.

 


See how an invalid request travels through given(), when() and then() — and where each assertion fails — in the REST Assured Visualizer.

From Real Projects

I've tested APIs at the level of CRUD operations, HTTP methods and JSON path validation, and written automation in Java with TestNG. REST Assured brings those together in one Java library — which is why testers with Selenium and TestNG experience usually pick it up quickly. Start with one resource and automate its full CRUD cycle. Testsigma supports web, mobile and API test automation, so understanding APIs was part of understanding the product I was testing. Invalid input should return a 4xx code with a clear message, never a 500.