Introduction

In our previous post, we explored GET Requests in REST Assured, learning how to retrieve data from APIs. Now, we’ll dive into POST Requests, which are used to create new resources on the server. This guide is designed for beginners and experienced developers, providing clear explanations and practical examples to help you master POST requests in REST Assured.

Key Point: POST requests send data to an API to create new resources, such as adding a new user or post, and REST Assured simplifies this process with its intuitive syntax.

What is a POST Request?

A POST Request is an HTTP method used to send data to a server to create a new resource. Unlike GET requests, which retrieve data, POST requests typically include a request body (e.g., JSON or XML) containing the data for the new resource. For example, sending a POST request to /users with a JSON payload can create a new user.

In REST Assured, POST requests are performed using the post() method, often combined with headers, query parameters, or a request body to define the resource details.

Performing POST Requests in REST Assured

Let’s explore how to perform and validate POST requests using REST Assured, using the public API https://jsonplaceholder.typicode.com for examples.

Option 1: Basic POST Request with JSON Body

The most common way to send a POST request is with a JSON request body, defined as a string.


import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

public class BasicPostTest {

    @Test
    public void testBasicPost() {
        RestAssured.baseURI = "https://jsonplaceholder.typicode.com";

        String jsonBody = "{\"title\": \"Test Post\", \"body\": \"This is a test post\", \"userId\": 1}";

        given()
            .contentType("application/json")
            .body(jsonBody)
            .when()
                .post("/posts")
            .then()
                .statusCode(201)
                .body("title", equalTo("Test Post"))
                .body("userId", equalTo(1))
                .body("id", notNullValue());
    }
}

Explanation:

  • contentType("application/json"): Sets the Content-Type header to indicate a JSON payload.
  • body(jsonBody): Sends the JSON string as the request body.
  • post("/posts"): Sends a POST request to create a new post.
  • then(): Validates the response:
    • statusCode(201): Ensures the resource was created (201 Created).
    • body("title", equalTo("Test Post")): Verifies the post’s title.
    • body("userId", equalTo(1)): Confirms the user ID.
    • body("id", notNullValue()): Checks that the server assigned an ID.
Important: Always set the correct Content-Type header (e.g., application/json) to match the request body format, or the API may reject the request.

Option 2: POST Request with Java Object

For cleaner code, use a Java object as the request body. REST Assured automatically serializes the object to JSON if a library like Jackson is included.

First, ensure the Jackson dependency is in your pom.xml:



    com.fasterxml.jackson.core
    jackson-databind
    2.15.2
    test

Now, create a Java class and use it in a POST request:


import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

// Java class for the request body
class Post {
    private String title;
    private String body;
    private int userId;

    public Post(String title, String body, int userId) {
        this.title = title;
        this.body = body;
        this.userId = userId;
    }

    // Getters and setters
    public String getTitle() { return title; }
    public void setTitle(String title) { this.title = title; }
    public String getBody() { return body; }
    public void setBody(String body) { this.body = body; }
    public int getUserId() { return userId; }
    public void setUserId(int userId) { this.userId = userId; }
}

public class PostObjectTest {

    @Test
    public void testPostWithObject() {
        RestAssured.baseURI = "https://jsonplaceholder.typicode.com";

        Post post = new Post("Test Post", "This is a test post", 1);

        given()
            .contentType("application/json")
            .body(post)
            .when()
                .post("/posts")
            .then()
                .statusCode(201)
                .body("title", equalTo("Test Post"))
                .body("userId", equalTo(1));
    }
}

Explanation:

  • Post: A Java class representing the JSON structure.
  • body(post): REST Assured serializes the Post object to JSON.
  • This approach reduces errors compared to writing JSON strings manually.

Option 3: POST Request with Request Specification

Use a Request Specification to reuse common settings like headers or base URI for POST requests.


import io.restassured.builder.RequestSpecBuilder;
import io.restassured.specification.RequestSpecification;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

public class PostWithSpecTest {

    private static RequestSpecification requestSpec;

    @BeforeAll
    public static void setup() {
        requestSpec = new RequestSpecBuilder()
            .setBaseUri("https://jsonplaceholder.typicode.com")
            .setContentType("application/json")
            .build();
    }

    @Test
    public void testPostWithSpec() {
        String jsonBody = "{\"title\": \"Test Post\", \"body\": \"This is a test\", \"userId\": 1}";

        given()
            .spec(requestSpec)
            .body(jsonBody)
            .when()
                .post("/posts")
            .then()
                .statusCode(201)
                .body("title", equalTo("Test Post"));
    }
}

Explanation:

  • setContentType("application/json"): Sets the default content type in the specification.
  • spec(requestSpec): Applies the specification, while the test provides the specific JSON body.
Pro Tip: Use Request Specifications for POST requests to centralize common settings, making tests more maintainable and reducing code duplication.

Step 1: Combining POST with Path and Query Parameters

POST requests can include path parameters or query parameters for more complex scenarios.


import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

public class PostWithParamsTest {

    @Test
    public void testPostWithParams() {
        RestAssured.baseURI = "https://jsonplaceholder.typicode.com";

        String jsonBody = "{\"title\": \"Test Comment\", \"body\": \"This is a comment\", \"userId\": 1}";

        given()
            .contentType("application/json")
            .pathParam("postId", 1)
            .queryParam("userId", 1)
            .body(jsonBody)
            .when()
                .post("/posts/{postId}/comments")
            .then()
                .statusCode(201)
                .body("title", equalTo("Test Comment"));
    }
}

Explanation:

  • pathParam("postId", 1): Specifies the post ID in the URL (/posts/1/comments).
  • queryParam("userId", 1): Adds a query parameter to filter or customize the request.
  • The test creates a comment for a specific post and validates the response.

Step 2: Extracting Response Data

You can extract the response from a POST request for further validation or processing.


import io.restassured.RestAssured;
import io.restassured.response.Response;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.*;

public class PostExtractResponseTest {

    @Test
    public void testExtractPostResponse() {
        RestAssured.baseURI = "https://jsonplaceholder.typicode.com";

        String jsonBody = "{\"title\": \"Test Post\", \"body\": \"This is a test\", \"userId\": 1}";

        Response response = given()
            .contentType("application/json")
            .body(jsonBody)
            .when()
                .post("/posts")
            .then()
                .statusCode(201)
                .extract().response();

        int id = response.path("id");
        System.out.println("Created Post ID: " + id);

        // Additional validation
        assert id > 0;
    }
}

Explanation:

  • extract().response(): Extracts the full response for further processing.
  • response.path("id"): Retrieves the id field from the JSON response.
  • This is useful for validating or storing the ID of the created resource.

Step 3: Verify Setup with pom.xml

Ensure your pom.xml includes dependencies for REST Assured, JUnit, and Jackson (for JSON serialization):



    
        io.rest-assured
        rest-assured
        5.4.0
        test
    
    
        org.junit.jupiter
        junit-jupiter
        5.10.2
        test
    
    
        org.hamcrest
        hamcrest
        2.2
        test
    
    
        com.fasterxml.jackson.core
        jackson-databind
        2.15.2
        test
    

Run the tests using mvn test or your IDE’s test runner to confirm the setup.

Tips for Beginners

  • Validate Payloads: Ensure the request body matches the API’s expected structure.
  • Use Java Objects: Prefer Java objects over JSON strings for cleaner code.
  • Check Status Codes: Expect 201 for successful resource creation, or 200 if the API deviates from standard REST practices.
  • Enable Logging: Use RestAssured.enableLoggingOfRequestAndResponseIfValidationFails() to debug issues.
Troubleshooting Tip: If a POST request returns a 400 Bad Request error, verify the request body, Content-Type header, and endpoint URL against the API documentation.

What’s Next?

In the next post, we’ll cover PUT Requests, exploring how to update resources using REST Assured. Stay tuned for more hands-on examples!