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
andassertTrue
, 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
andmvn 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.