-
Notifications
You must be signed in to change notification settings - Fork 0
JPostman Tutorial Part 6: Fluent API with TestNG and JUnit
-
Video tutorial: https://youtu.be/mX2k8O6oGM0
In this tutorial, we continue improving JPostman test code with fluent API method chaining.
We start from the native TestNG flow and refactor the code to reduce boilerplate, remove unnecessary local variables, move request and response handling into the same fluent chain, and cache access token execution results. Then we convert the same example to JUnit with only small code changes.
This tutorial also shows how to avoid TestNG-specific dependsOnMethods so the same testing pattern can work across different Java test frameworks.
By the end of this tutorial, you will know how to:
- Replace
SecureContextwithTestNgContext. - Use native JPostman TestNG soft assertions.
- Replace manual
SoftAssertusage with JPostman assertion helpers. - Use fluent API method chaining for response validation.
- Use
verify()andtearDown()to run response verification after each test. - Keep request and response data inside the same
TestNgContext. - Use lambda expressions inside the fluent API chain.
- Store values with the JPostman context cache helper.
- Remove TestNG
dependsOnMethodsfrom dependent tests. - Cache access token execution results with a lambda expression.
- Convert the TestNG example to JUnit.
- Use
@JPostmanJUnit(printFailures = true)to print JUnit failure details.
Before starting this tutorial, make sure you completed the previous tutorials:
- Part 1: Create a Java Maven API testing project with JPostman.
- Part 2: Execute REST API requests using RestAssured.
- Part 3: Chain API requests using an access token.
- Part 4: Protect request and response logs with
jpostman-secure. - Part 5: Use native TestNG support and fluent API testing.
You should already have:
- A Maven test project.
- Exported Postman collection and environment JSON files.
- A secure rule policy file such as
demo_test_rule.ini. -
jpostman-testngconfigured. -
jpostman-restassuredconfigured. - A working TestNG test that logs in, caches an access token, and calls an authenticated user API.
First, replace SecureContext with TestNgContext.
Then update the package import from:
io.jpostman.secureto:
io.jpostman.testngThis moves the test from the generic secure context into the native JPostman TestNG context.
JPostman assertion classes now support soft assertions natively.
This means you can remove the manual TestNG SoftAssert import and declaration, then use JPostman soft assertion helpers directly from the context.
Example:
base.soft()You can also enable secure failure logging:
base.soft(true)Instead of calling TestNG assertions directly, use the JPostman assertion methods.
Examples include:
base.soft(true).statusCode(200);
base.soft(true).exists("accessToken", "Access token not found");The exists(...) method is useful because it validates that a response field is available before reading it with path(...).
Instead of repeating the context for each assertion, chain the assertions together.
Example:
base.soft(true)
.statusCode(200)
.exists("accessToken", "Access token not found")
.verify();This reduces repeated code and keeps the response validation easier to read.
Instead of calling verify() in every test method, move verification into a tearDown method and annotate it with TestNG @AfterMethod.
Example:
@AfterMethod
public void tearDown() {
base.verify();
}This allows verification to run after each test method, even when the test method throws an exception.
To avoid using a shared base reference inside every test method, create a local TestNgContext for the request flow.
Example:
TestNgContext ctx = base.request(col.getRequest("Login user and get tokens"));After the response is initialized, the same context can provide response values such as:
ctx.path("accessToken")Use .response(...) directly after .request(...).
Example:
base.request(col.getRequest("Login user and get tokens"))
.response(c -> RestAssuredExecutor.execute(c.request()));The lambda expression receives the current context, so the request and response stay inside the same fluent chain.
Starting with JPostman release 1.2.0, you can run custom logic inside the fluent chain.
Example:
base.request(col.getRequest("Login user and get tokens"))
.response(c -> RestAssuredExecutor.execute(c.request()))
.context(c -> {
c.soft(true).exists("accessToken", "Access token not found");
c.cache("accessToken", c.path("accessToken"));
});This keeps assertions, cache updates, and response handling together.
dependsOnMethods is specific to TestNG.
For cross-framework testing, remove this dependency and cache the access token execution result instead.
Example:
public String getTokens() {
return base.cache(() -> {
System.out.println("############ Get AccessToken ############");
return base.request(col.getRequest("Login user and get tokens"))
.response(c -> RestAssuredExecutor.execute(c.request()))
.context(c -> c.soft(true).exists("accessToken", "Access token not found"))
.path("accessToken");
});
}This allows multiple tests to call the same helper method while the token request runs only once.
If the same function needs to generate different tokens, pass a method argument and use it as the cache key.
Example:
public String getTokens(String name) {
return base.cache(() -> {
System.out.println("############ Get AccessToken - " + name + " ############");
return base.request(col.getRequest("Login user and get tokens"))
.response(c -> RestAssuredExecutor.execute(c.request()))
.context(c -> c.soft(true).exists("accessToken", "Access token not found"))
.path("accessToken");
}, name);
}Then call:
getTokens("user1");
getTokens("user2");Before demonstrating the JUnit changes, copy the current class and rename it.
Then update the imports and annotations.
Replace:
testng.annotations
with:
junit.jupiter.api
Change:
@BeforeClassto:
@BeforeAllChange:
@AfterMethodto:
@AfterEachAlso add the jpostman-junit dependency to pom.xml.
When running JUnit, output may not appear directly in the console. You may need to open the JUnit Result window.
JPostman improves this behavior with:
import io.jpostman.junit.JPostmanJUnit;and:
@JPostmanJUnit(printFailures = true)This prints failure details when a JUnit test fails.
A simplified fluent access token helper can look like this:
public String getTokens(String name) {
return base.cache(() -> {
System.out.println("############ Get AccessToken - " + name + " ############");
return base.request(col.getRequest("Login user and get tokens"))
.response(c -> RestAssuredExecutor.execute(c.request()))
.context(c -> c.soft(true).exists("accessToken", "Access token not found"))
.path("accessToken");
}, name);
}A test can then call:
base.request(col.getRequest("Get current auth user"))
.response(c -> RestAssuredExecutor
.apply(c.request())
.auth()
.oauth2(getTokens("user1"))
.response());This test flow:
- Loads the Postman collection and environment.
- Uses native JPostman TestNG or JUnit context support.
- Resolves request values from the secure context.
- Executes requests with RestAssured.
- Validates responses with JPostman assertions.
- Runs verification after each test.
- Caches access token execution results.
- Avoids TestNG-only
dependsOnMethods. - Reuses the same testing style for both TestNG and JUnit.
This approach makes JPostman tests easier to maintain because it:
- Reduces local variables.
- Keeps request, response, assertion, and cache logic together.
- Supports reusable access token helpers.
- Avoids test framework-specific execution dependencies.
- Makes it easier to move between TestNG and JUnit.
- Keeps secure failure logs available for debugging.
In this tutorial, we refactored the TestNG example with JPostman fluent API method chaining, native soft assertions, response verification, lambda-based custom logic, and cached token execution.
We also removed dependsOnMethods and converted the same flow to JUnit with small annotation and dependency changes.
In the next video, we will run the tests from Maven and review additional executors beyond RestAssured, such as Java HttpClient, Playwright, and Unirest.
- Slides: https://1drv.ms/p/c/5259373e58768a70/IQCYnGMtgO6_Q5F8BzMll2SoATrH5QkPv9F4P5TizX7TeDg?e=FtmQ6u&action=embedview
- JPostman API Documentation: https://jpostman.github.io/jpostman/
- JPostman GitHub repository: https://github.com/JPostman/jpostman
- JPostman Wiki: https://github.com/JPostman/jpostman/wiki
- DummyJSON API: https://dummyjson.com