Introduction

In our REST Assured series, we’ve covered topics like REST Assured with TestNG, Request and Response Logging, and Hamcrest Matchers, providing a comprehensive toolkit for API testing. Now, we’ll focus on integrating REST Assured with JUnit, a widely-used testing framework that offers simplicity and robust features for writing API tests. This guide demonstrates how to use REST Assured with JUnit 5 (Jupiter) for structured and maintainable tests, with practical examples and best practices. It’s designed for beginners and experienced developers, ensuring you can build effective API tests with JUnit.

Key Point: Integrating REST Assured with JUnit 5 provides a straightforward and structured approach to API testing, leveraging annotations, assertions, and parameterized tests for clarity and scalability.

Why Use JUnit with REST Assured?

JUnit is a popular testing framework for Java, with JUnit 5 (Jupiter) offering modern features for API testing, including:

  • Annotations: Flexible setup and teardown with @BeforeEach, @AfterEach, and @Test.
  • Assertions: Rich assertion methods like assertEquals and assertTrue, alongside Hamcrest Matchers.
  • Parameterized Tests: Run tests with multiple inputs using @ParameterizedTest.
  • Extensions: Support for integrations like Allure for reporting.
  • Simplicity: Easy-to-learn syntax, ideal for beginners and small-to-medium test suites.

REST Assured integrates seamlessly with JUnit, using its fluent API for requests and assertions. We’ll use https://jsonplaceholder.typicode.com for examples, testing endpoints like /posts to demonstrate JUnit 5 features.

Setting Up REST Assured with JUnit

We’ll set up a Maven project with REST Assured, JUnit 5, and Allure for reporting, consistent with earlier posts in the series. The junit-jupiter dependency supports JUnit 5, and allure-junit5 enables reporting.

Here’s the pom.xml, styled with your preferred Blogger format for XML syntax highlighting:



    4.0.0
    com.example
    rest-assured-junit
    1.0-SNAPSHOT

    
        11
        2.27.0
        1.9.22
    

    
        
            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
        
        
            io.qameta.allure
            allure-junit5
            ${allure.version}
            test
        
    

    
        
            
                org.apache.maven.plugins
                maven-surefire-plugin
                3.2.5
                
                    
                        -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
                    
                
                
                    
                        org.aspectj
                        aspectjweaver
                        ${aspectj.version}
                    
                
            
            
                io.qameta.allure
                allure-maven
                2.12.0
                
                    ${allure.version}
                
            
        
    

No additional setup is required for https://jsonplaceholder.typicode.com. All tests will use JUnit 5 annotations and REST Assured’s fluent API.

Using REST Assured with JUnit

Let’s explore how to write API tests with REST Assured and JUnit 5, leveraging its key features.

Example 1: Basic Test with JUnit Annotations

Write a simple API test using JUnit 5 annotations for setup and test execution.


import io.qameta.allure.Description;
import io.qameta.allure.Feature;
import io.restassured.RestAssured;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

@Feature("REST Assured with JUnit")
public class BasicJUnitTest {

    @BeforeEach
    public void setup() {
        RestAssured.baseURI = "https://jsonplaceholder.typicode.com";
    }

    @Test
    @DisplayName("Test fetching a single post")
    @Description("Test fetching a single post with JUnit")
    public void testGetPost() {
        given()
            .log().all()
        .when()
            .get("/posts/1")
        .then()
            .log().all()
            .statusCode(200)
            .body("id", equalTo(1))
            .body("title", notNullValue());
    }
}

Explanation:

  • @BeforeEach: Sets up the base URI before each test.
  • @DisplayName: Provides a readable test name for reports.
  • @Test: Defines the test case, using REST Assured with Hamcrest Matchers.
Important: Use @BeforeEach and @AfterEach for per-test setup and teardown to ensure test isolation.

Example 2: Parameterized Testing

Use @ParameterizedTest to test multiple post IDs.


import io.qameta.allure.Description;
import io.qameta.allure.Feature;
import io.restassured.RestAssured;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

@Feature("REST Assured with JUnit")
public class ParameterizedJUnitTest {

    @BeforeEach
    public void setup() {
        RestAssured.baseURI = "https://jsonplaceholder.typicode.com";
    }

    @ParameterizedTest(name = "Test fetching post with ID {0}")
    @ValueSource(ints = {1, 2, 3})
    @Description("Test fetching posts with different IDs using ParameterizedTest")
    public void testGetPosts(int postId) {
        given()
            .log().all()
        .when()
            .get("/posts/{id}", postId)
        .then()
            .log().all()
            .statusCode(200)
            .body("id", equalTo(postId))
            .body("userId", greaterThan(0));
    }
}

Explanation:

  • @ParameterizedTest: Runs the test for each value provided by @ValueSource.
  • name = "...": Customizes the test name in reports for clarity.
  • Each test iteration logs the request and response for debugging.

Example 3: Using JUnit Assertions

Combine REST Assured with JUnit assertions for response validation.


import io.qameta.allure.Description;
import io.qameta.allure.Feature;
import io.restassured.RestAssured;
import io.restassured.response.Response;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.*;
import static org.junit.jupiter.api.Assertions.*;

@Feature("REST Assured with JUnit")
public class JUnitAssertionsTest {

    @BeforeEach
    public void setup() {
        RestAssured.baseURI = "https://jsonplaceholder.typicode.com";
    }

    @Test
    @DisplayName("Test fetching a post with JUnit assertions")
    @Description("Test fetching a post with JUnit assertions")
    public void testGetPostWithAssertions() {
        Response response = given()
            .log().all()
        .when()
            .get("/posts/1")
        .then()
            .log().all()
            .statusCode(200)
            .extract().response();

        assertEquals(1, response.path("id"), "Post ID should be 1");
        assertNotNull(response.path("title"), "Title should not be null");
        assertTrue(response.path("userId") > 0, "User ID should be positive");
    }
}

Explanation:

  • extract().response(): Extracts the response for further validation.
  • assertEquals, assertNotNull, assertTrue: JUnit assertions validate response data.
  • JUnit assertions provide detailed failure messages, complementing Hamcrest Matchers.
Pro Tip: Use JUnit assertions for complex validations or when you need custom failure messages, and Hamcrest for fluent, readable assertions.

Example 4: Testing POST Requests

Test a POST request to create a resource, using JUnit annotations.


import io.qameta.allure.Description;
import io.qameta.allure.Feature;
import io.restassured.RestAssured;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

@Feature("REST Assured with JUnit")
public class PostRequestTest {

    @BeforeEach
    public void setup() {
        RestAssured.baseURI = "https://jsonplaceholder.typicode.com";
    }

    @Test
    @DisplayName("Test creating a post")
    @Description("Test creating a post with JUnit")
    public void testCreatePost() {
        String requestBody = "{\"title\": \"Test Post\", \"body\": \"This is a test\", \"userId\": 1}";

        given()
            .header("Content-Type", "application/json")
            .body(requestBody)
            .log().all()
        .when()
            .post("/posts")
        .then()
            .log().all()
            .statusCode(201)
            .body("id", notNullValue())
            .body("title", equalTo("Test Post"));
    }
}

Explanation:

  • Sends a POST request to create a post, with JSON payload.
  • Verifies the response status (201 Created) and response body.
  • Note: jsonplaceholder.typicode.com simulates creation but doesn’t persist data.

Example 5: Logging and Allure Integration

Integrate logging and Allure reporting with JUnit.


import io.qameta.allure.Allure;
import io.qameta.allure.Description;
import io.qameta.allure.Feature;
import io.restassured.RestAssured;
import io.restassured.response.Response;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

@Feature("REST Assured with JUnit")
public class AllureJUnitTest {

    @BeforeEach
    public void setup() {
        RestAssured.baseURI = "https://jsonplaceholder.typicode.com";
    }

    @Test
    @DisplayName("Test fetching a post with Allure logging")
    @Description("Test fetching a post with Allure logging")
    public void testAllureLogging() {
        Response response = given()
            .log().all()
        .when()
            .get("/posts/1")
        .then()
            .log().all()
            .statusCode(200)
            .body("id", equalTo(1))
            .extract().response();

        Allure.addAttachment("Response Body", "application/json", response.asString(), ".json");
    }
}

Explanation:

  • Allure.addAttachment: Attaches the response body to the Allure report.
  • log().all(): Logs request and response details for debugging.
  • Run mvn clean test and mvn allure:serve to view the report.

Integrating with CI/CD

Add JUnit-based tests to a GitHub Actions pipeline for automation.

Create or update .github/workflows/ci.yml:


name: REST Assured JUnit CI Pipeline

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  build-and-test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up JDK 11
        uses: actions/setup-java@v4
        with:
          java-version: '11'
          distribution: 'temurin'

      - name: Cache Maven dependencies
        uses: actions/cache@v4
        with:
          path: ~/.m2/repository
          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
          restore-keys: ${{ runner.os }}-maven-

      - name: Run tests
        run: mvn clean test

      - name: Generate Allure report
        run: mvn allure:report

      - name: Upload Allure results
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: allure-results
          path: target/allure-results

      - name: Publish Allure report
        if: always()
        uses: simple-elf/allure-report-action@v1.7
        with:
          allure_results: target/allure-results
          gh_pages: gh-pages
          allure_report: allure-report

      - name: Deploy report to GitHub Pages
        if: always()
        uses: peaceiris/actions-gh-pages@v4
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: allure-report

Explanation:

  • Runs JUnit tests with mvn clean test.
  • Publishes Allure reports to GitHub Pages for visibility.

Tips for Beginners

  • Use Descriptive Names: Leverage @DisplayName for clear test names in reports.
  • Combine Assertions: Use JUnit assertions for complex logic and Hamcrest for fluent checks.
  • Test Isolation: Ensure tests are independent using @BeforeEach for setup.
  • Enable Logging: Use log().all() for debugging failed tests.
Troubleshooting Tip: If a test fails, enable log().all() to inspect request/response details and use JUnit’s detailed assertion messages to pinpoint issues.

What’s Next?

This post enhances our REST Assured series by integrating JUnit 5, providing a simple yet powerful framework for API testing. To continue your learning, consider exploring:

  • GraphQL Testing: Testing GraphQL APIs with REST Assured.
  • Advanced Allure Reporting: Customizing reports with environments and categories.
  • End-to-End Testing: Combining REST Assured with Selenium for UI and API testing.
Stay tuned for more testing tutorials!