Skip to content
CodeKruPro

Handle Validation Errors

19/62

Handle Validation Errors

When validation fails, the API returns 400 Bad Request with {"valid": false, "errors": [...]}.

Sending an empty name and no email: {"name": ""} triggers both validation errors.

Task:

  1. POST to /validate/json with body {"name": ""}
  2. Print the status, valid flag, error count, and each error

Expected output:

Status: 400
Valid: false
Error count: 2
- Field 'name' is required and must not be empty
- Field 'email' is required and must not be empty

About this lesson

REST Assured 400 Bad Request: read the list of validation errors with getList()

Learn REST AssuredIntermediatePOST Requests

How it works

A good API does not stop at the first problem in a payload. It checks every rule and returns all the failures together, so a client can fix them in one pass. testkru does this on /validate/json: an empty name and a missing email produce status 400, valid set to false, and an errors array with one human-readable message per broken rule, name first and email second.

In REST Assured a 400 is not an exception. The Response object holds whatever came back, so you can read the status with getStatusCode() and parse the error body exactly as you would a success. Only an assertion such as then().statusCode(200) turns an unexpected status into a failure.

JSON arrays map to Java lists. jsonPath().getList("errors") returns a List you can size and loop over, and the overload that takes String.class gives you a typed List<String>. For assertions, Hamcrest offers hasSize() to pin the count and hasItem() with containsString() to check that one message mentions a given field.

About the assignment

Trigger both validation rules at once by sending a payload whose name is blank and which has no email, then report the status, the flag, how many errors came back and each message on its own line.

What you will do

  1. POST the starter payload, a single empty name, to /validate/json with the JSON content type.
  2. Print the status code after Status: and the boolean valid field after Valid:.
  3. Pull the errors array out as a list with getList() and print its size after Error count:.
  4. Loop over the list and print every message prefixed by a dash and a space, keeping the order the server used.

Common mistakes

  • Expecting an exception on 400

    Nothing is thrown when the server rejects the payload. If your code assumes a failure will stop the program, it carries on with a body that has no data object. Check the status explicitly.

  • Calling getList() on a success body

    When the payload is valid there is no errors key, and getList("errors") returns null. Calling size() on that throws a NullPointerException, so guard the call if the same code handles both outcomes.

  • Asserting on exact message text everywhere

    Messages are written for people and change more often than field names. Checking the count with hasSize(2) and the field with containsString("email") keeps the test useful after a copy edit.

In a real test suite

Negative tests like this one are where API suites earn their keep. A typical JUnit 5 class has one test per rule: blank name, missing email, malformed email, each asserting a 400 and the matching entry in the array.

Teams often add a parameterised test that feeds a table of bad payloads through the same request and checks the expected error for each row.

To try one of these calls on any API endpoint without a task, open the Online Selenium Java Compiler (REST Assured is included).

Starter code

The editor above opens with this code. Fill in the TODO lines, then run and submit it.

Main.java
import io.restassured.RestAssured;
import io.restassured.response.Response;
import io.restassured.specification.RequestSpecification;
import io.restassured.http.ContentType;
import static io.restassured.RestAssured.*;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        RestAssured.baseURI = "https://testkru.com/api";

        // TODO: POST to /validate/json with body: {"name": ""}
        // TODO: Print status code
        // TODO: Print the "valid" field
        // TODO: Get the "errors" list and print its size
        // TODO: Loop through errors and print each with "- " prefix
    }
}