Enterprise Java

Asserting JSON Responses with REST-Assured in Java

This article explores how to use Java REST-assured to efficiently assert JSON responses in REST API testing. REST-assured is a Java library specifically designed for testing REST APIs, allowing developers to make HTTP calls and verify responses with ease. When working with APIs, verifying JSON response structures and values is essential to ensure data accuracy and consistency across applications. The article will also focus on asserting properties within arrays in JSON responses.

1. Sample JSON Structure

To understand how we can assert JSON responses effectively, let’s start with an overview of a sample JSON structure that represents a typical API response. This structure will serve as the basis for illustrating different assertion techniques using Java REST-assured.

Consider the following JSON response from an API endpoint that provides user session information:

{
  "activeSession": true,
  "token": "abc123",
  "details": [
    {
      "accountType": 2,
      "accountDescription": "Premium",
      "username": "mr_fish",
      "clientId": 42
    }
  ]
}

This JSON has an array field details, and our goal is to verify the values of the properties within that array.

Here is a controller class, SessionInfoController, to handle the HTTP request and produce the above JSON response.

@RestController
@RequestMapping("/api")
public class SessionInfoController {

    @GetMapping("/session-info")
    public Map<String, Object> getSessionInfo() {

        Map<String, Object> sessionInfo = Map.of(
                "activeSession", true,
                "token", "abc123",
                "details", Collections.singletonList(
                        Map.of(
                                "accountType", 2,
                                "accountDescription", "Premium",
                                "username", "mr_fish",
                                "clientId", 42
                        )
                )
        );

        return sessionInfo;
    }
}

2. Setting Up REST-assured

To begin, it’s essential to have REST-assured configured in the project. Adding REST-assured to the project dependencies will enable testing of JSON responses. For configuration with Maven, include the following dependency in the pom.xml file:

        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>5.4.0</version>
            <scope>test</scope>
        </dependency>

3. Example Test: Asserting Array Properties

Consider an endpoint /session-info that returns this JSON data. The test will be structured to validate each property’s values precisely. Begin by setting REST-assured’s base URI to point to the API server. Then, write the test case using REST-assured’s given(), when(), and then() methods to define assertions for each JSON field, ensuring the response data aligns with expected values.

The body() method in REST-assured is essential for checking specific fields in a JSON response. Used with equalTo(), it verifies that each field has the correct value, ensuring the data is accurate and consistent.

public class SessionInfoTest {

    @BeforeAll
    public static void setup() {
        RestAssured.baseURI = "http://localhost:8080/api";
    }

    @Test
    public void testSessionInfoResponse() {
        given()
                .contentType(ContentType.JSON)
                .when()
                .get("/session-info")
                .then()
                .statusCode(200)
                .body("activeSession", equalTo(true))
                .body("token", equalTo("abc123"))
                .body("details", hasSize(1))
                .body("details[0].accountType", equalTo(2))
                .body("details[0].accountDescription", equalTo("Premium"))
                .body("details[0].username", equalTo("mr_fish"))
                .body("details[0].clientId", equalTo(42));
    }
}

Here’s an explanation of each assertion.

  • body("activeSession", equalTo(true)): Asserts that the activeSession property is true.
  • body("token", equalTo("abc123")): Verifies that the token field matches the expected string "abc123".
  • body("details", hasSize(1)): Checks that the details array has exactly one object.
  • body("details[0].accountType", equalTo(2)): Asserts that the accountType field in the first element of details is 2.
  • body("details[0].accountDescription", equalTo("Premium")): Verifies the accountDescription field is "Premium".
  • body("details[0].username", equalTo("mr_fish")): Checks the username field is "mr_fish".
  • body("details[0].clientId", equalTo(42)): Asserts that the clientId field in the first element of details is 42.

3.1 Asserting the Entire JSON Body as a String

REST-assured provides the .extract() method, which allows us to capture the response after performing assertions. This approach is useful for checking the full structure and content of the response in one assertion.

    @Test
    public void testWholeJsonBody() {
        // Extract the JSON response body as a string
        String body = given()
                .get("/session-info")
                .then()
                .extract()
                .body()
                .asString();

        // Assert the entire JSON structure as a single string
        assertThat(body)
                .isEqualTo("{\"details\":[{\"accountDescription\":\"Premium\",\"clientId\":42,\"username\":\"mr_fish\",\"accountType\":2}],\"activeSession\":true,\"token\":\"abc123\"}");
    }
}

  • Extracting JSON as String: The given().get("/session-info").then().extract().body().asString() retrieves the JSON response body from the /session-info endpoint as a single string.
  • Asserting the JSON String: Using assertThat(body).isEqualTo(...), we directly compare the extracted JSON string to the expected JSON string to ensure that the entire response body matches exactly.

4. Asserting With JSONAssert

Comparing JSON as plain strings can lead to test failures due to field ordering differences. We might encounter errors which indicate that the actual JSON response has fields in a different order than expected. JSON objects do not enforce a specific order for fields, so this discrepancy can occur without affecting the content’s meaning.

To handle this, we can use JSONAssert to perform a relaxed comparison that ignores the order of fields. Here’s how to modify the test to use JSONAssert for an order-independent assertion.

    @Test
    void whenGetBody_thenCanCompareByWholeString() throws Exception {
        // Extract the JSON response body as a string
        String body = given()
            .get("/session-info")
            .then()
            .extract()
            .body()
            .asString();

        // Expected JSON string
        String expectedJson = "{\"activeSession\":true,\"token\":\"abc123\",\"details\":[{\"accountType\":2,\"accountDescription\":\"Premium\",\"username\":\"mr_fish\",\"clientId\":42}]}";

        // Assert JSON, ignoring field order
        JSONAssert.assertEquals(expectedJson, body, JSONCompareMode.LENIENT);
    }
  • JSONAssert.assertEquals(): This method allows for JSON comparisons that are tolerant of field order, preventing test failures due to differences in JSON key ordering.
  • JSONCompareMode.LENIENT: This mode ignores field order, comparing only the structure and values within the JSON data. This approach ensures that tests pass as long as all required fields and values are present, regardless of their order.

5. Asserting JSON with JSON Assert Hamcrest and JSON Unit Hamcrest

When dealing with JSON responses that contain dynamic or changeable fields, JSON Assert Hamcrest and JSONUnit Hamcrest provide effective ways to handle these variances while allowing the test to focus on expected fields and values. Both libraries can be used in combination with REST-assured for flexible assertions that ignore extra fields.

Adding Dependencies for JSON Assert Hamcrest and JSONUnit Hamcrest

To use JSON Assert Hamcrest and JSON Unit Hamcrest, the following dependencies should be added to the pom.xml:

<dependency>
    <groupId>uk.co.datumedge</groupId>
    <artifactId>hamcrest-json</artifactId>
    <version>0.2</version>
</dependency>

<dependency>
    <groupId>net.javacrumbs.json-unit</groupId>
    <artifactId>json-unit</artifactId>
    <version>2.27.0</version>
    <scope>test</scope>
</dependency>

5.1 Using JSON Assert Hamcrest

With JSON Assert Hamcrest, we can load an expected JSON structure from a file and assert it against the response while allowing extra fields in the JSON. Assuming we have an expected.json file containing the expected JSON structure in the src/test/resources directory. Here’s how to write a test using JSON Assert Hamcrest:

    @Test
    void assertJsonWithExtraFields_JsonAssert() {
        given()
                .get("/session-info")
                .then()
                .body(sameJSONAs(Files.contentOf(new File("src/test/resources/expected.json"), StandardCharsets.UTF_8))
                        .allowingExtraUnexpectedFields());
    }

In this example:

  • sameJSONAs: Loads the expected JSON structure from expected.json and compares it to the actual JSON response.
  • allowingExtraUnexpectedFields(): Ignores any additional fields in the actual JSON response, focusing on matching fields in the expected JSON.

5.2 Using JSONUnit Hamcrest

With JSONUnit Hamcrest, we can use options to make comparisons more flexible, such as ignoring extra fields or handling nested fields.

    @Test
    void compareFieldsWithJsonUnitIgnoringExtras() {
        given()
            .get("/session-info")
            .then()
            .body(jsonEquals(Files.contentOf(new File("src/test/resources/expected.json"), StandardCharsets.UTF_8))
            .when(Option.IGNORING_EXTRA_FIELDS));
    }

In this example:

  • jsonEquals: Compares the actual JSON response to the expected JSON structure loaded from the file.
  • Option.IGNORING_EXTRA_FIELDS: Ignores any additional fields not specified in expected.json, ensuring only relevant fields are validated.

6. Conclusion

In this article, the use of REST-assured for asserting JSON responses in Java has been explored, demonstrating several techniques for validating JSON structures effectively. By using REST-assured’s body() and equalTo() methods, along with additional tools like JSON Assert Hamcrest and JSON Unit Hamcrest, testers can achieve precise, flexible assertions that handle complex scenarios, including ignoring extra fields or comparing entire JSON bodies as strings.

7. Download the Source Code

This article focused on using Java REST-assured to assert JSON responses.

Download
You can download the full source code of this example here: java rest assured assert json responses

Omozegie Aziegbe

Omos Aziegbe is a technical writer and web/application developer with a BSc in Computer Science and Software Engineering from the University of Bedfordshire. Specializing in Java enterprise applications with the Jakarta EE framework, Omos also works with HTML5, CSS, and JavaScript for web development. As a freelance web developer, Omos combines technical expertise with research and writing on topics such as software engineering, programming, web application development, computer science, and technology.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button