Introduction

In our previous post, we explored Query Parameters in REST Assured, learning how to add dynamic key-value pairs to API requests. Now, we’ll dive into Path Parameters, which allow you to work with dynamic segments in API URLs. This guide is designed for beginners and experienced developers, offering clear explanations and practical examples to help you use path parameters effectively in REST Assured.

Key Point: Path parameters enable you to create flexible and reusable tests by dynamically replacing parts of the URL, making it easier to test specific resources in RESTful APIs.

What Are Path Parameters?

Path Parameters are placeholders in the URL path of an API request, used to identify specific resources. For example, in the URL https://api.example.com/users/1, the 1 is a path parameter representing a user ID. Unlike query parameters, which are appended after a question mark, path parameters are embedded directly in the URL path.

In REST Assured, you can define path parameters using the pathParam() method or by embedding them directly in the URL with placeholders. This makes your tests dynamic and reusable for different resource IDs or values.

Adding Path Parameters in REST Assured

REST Assured provides multiple ways to handle path parameters, making it easy to test APIs with dynamic endpoints. Let’s explore these approaches using the public API https://jsonplaceholder.typicode.com.

Option 1: Using pathParam()

The pathParam() method allows you to define a placeholder in the URL and assign it a value dynamically.


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

public class PathParamTest {

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

        given()
            .pathParam("userId", 1)
            .when()
                .get("/users/{userId}")
            .then()
                .statusCode(200)
                .body("id", equalTo(1))
                .body("name", notNullValue());
    }
}

Explanation:

  • pathParam("userId", 1): Defines a path parameter named userId with the value 1.
  • get("/users/{userId}"): Uses {userId} as a placeholder in the URL, which is replaced by the value 1, resulting in /users/1.
  • then(): Validates the response, ensuring the status code is 200 and the user’s id matches the path parameter.
Important: The placeholder name in the URL (e.g., {userId}) must match the name used in pathParam(). Mismatches will cause errors.

Option 2: Using Multiple Path Parameters

For APIs with multiple path parameters, use multiple pathParam() calls or the pathParams() method for conciseness.


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

public class MultiplePathParamTest {

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

        given()
            .pathParams("userId", 1, "postId", 1)
            .when()
                .get("/users/{userId}/posts/{postId}")
            .then()
                .statusCode(200)
                .body("userId", equalTo(1))
                .body("id", equalTo(1));
    }
}

Explanation:

  • pathParams("userId", 1, "postId", 1): Defines two path parameters, resulting in the URL /users/1/posts/1.
  • The test fetches a specific post for a user and validates its userId and id.

Option 3: Using Request Specification

To reuse path parameters across tests, include them in a Request Specification. This is useful when testing multiple endpoints with similar URL patterns.


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 PathParamSpecTest {

    private static RequestSpecification requestSpec;

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

    @Test
    public void testUserWithSpec() {
        given()
            .spec(requestSpec)
            .pathParam("userId", 1)
            .when()
                .get("/users/{userId}")
            .then()
                .statusCode(200)
                .body("id", equalTo(1));
    }

    @Test
    public void testPostWithSpec() {
        given()
            .spec(requestSpec)
            .pathParam("postId", 1)
            .when()
                .get("/posts/{postId}")
            .then()
                .statusCode(200)
                .body("id", equalTo(1));
    }
}

Explanation:

  • RequestSpecBuilder: Defines a reusable specification with the base URI and header.
  • pathParam(): Adds path parameters specific to each test.
  • spec(requestSpec): Applies the common configuration, while path parameters are added dynamically.
Pro Tip: Combine Request Specifications with path parameters to maintain consistent settings across tests while allowing flexibility for dynamic URLs.

Step 1: Handling Dynamic Path Parameters

Path parameters are often dynamic, varying based on test data. You can pass different values to the same endpoint to test multiple resources.


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

public class DynamicPathParamTest {

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

        int userId = 2; // Dynamic value
        given()
            .pathParam("userId", userId)
            .when()
                .get("/users/{userId}")
            .then()
                .statusCode(200)
                .body("id", equalTo(userId));
    }
}

Explanation:

  • userId: A variable that can be changed to test different users.
  • The test dynamically constructs the URL (e.g., /users/2) and validates the response.

Step 2: Combining Path and Query Parameters

You can combine path and query parameters for more complex requests.


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

public class CombinedParamsTest {

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

        given()
            .pathParam("userId", 1)
            .queryParam("id", 1)
            .when()
                .get("/users/{userId}/posts")
            .then()
                .statusCode(200)
                .body("[0].id", equalTo(1));
    }
}

Explanation:

  • pathParam("userId", 1): Sets the user ID in the URL path.
  • queryParam("id", 1): Adds a query parameter to filter posts.
  • The resulting URL is /users/1/posts?id=1.

Step 3: Verify Setup with pom.xml

Ensure your pom.xml includes the necessary dependencies for REST Assured and JUnit:



    
        io.rest-assured
        rest-assured
        5.4.0
        test
    
    
        org.junit.jupiter
        junit-jupiter
        5.10.2
        test
    
    
        org.hamcrest
        hamcrest
        2.2
        test
    

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

Tips for Beginners

  • Check API Documentation: Verify the correct path parameter names and URL structure in the API’s documentation.
  • Use Descriptive Placeholders: Name placeholders clearly (e.g., {userId}) to improve readability.
  • Test with Public APIs: Practice with jsonplaceholder.typicode.com for safe experimentation.
  • Enable Logging: Use RestAssured.enableLoggingOfRequestAndResponseIfValidationFails() to debug URL issues.
Troubleshooting Tip: If the API returns a 404 error, ensure the path parameter values and URL structure are correct. Mismatched placeholders or invalid IDs may cause failures.

What’s Next?

In the next post, we’ll cover Request Body (JSON, XML), exploring how to send data in API requests using REST Assured. Stay tuned for more hands-on examples!