惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Microsoft Azure Blog
Microsoft Azure Blog
Engineering at Meta
Engineering at Meta
A
About on SuperTechFans
T
The Blog of Author Tim Ferriss
I
InfoQ
博客园_首页
G
Google Developers Blog
爱范儿
爱范儿
Last Week in AI
Last Week in AI
量子位
阮一峰的网络日志
阮一峰的网络日志
雷峰网
雷峰网
酷 壳 – CoolShell
酷 壳 – CoolShell
Vercel News
Vercel News
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
GbyAI
GbyAI
月光博客
月光博客
The GitHub Blog
The GitHub Blog
V
Visual Studio Blog
N
Netflix TechBlog - Medium
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 司徒正美
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 聂微东

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
The REST Assured Setup Nobody Shows You: Handling Auth To...
muhammad San · 2026-04-23 · via DEV Community

muhammad Sanaev

Most REST Assured tutorials show you a single given().when().then() against a sample API and call it done. That's fine for learning the syntax, but it doesn't cover what you actually need on a real project things like config per environment, clean test structure, and handling auth tokens that expire while the suite is running.

I'm Mukhammadjon Sanaev, a QA Automation Engineer in San Francisco. I've worked across e-commerce, logistics, and sports tech. This post walks through a simple REST Assured + TestNG + Maven setup I'd use on day one of a new API testing project, plus one problem I ran into on a real checkout API that isn't in the tutorials.

What We're Building
A small Java project that:

Uses REST Assured for API calls
Uses TestNG as the test runner
Runs against dev or staging with a single command
Handles an auth token that expires mid-run

Examples are based on an e-commerce checkout API — the kind of thing you'd test at a Shopify- or Wayfair-style company. Nothing proprietary, just the shape of a real checkout flow.

Project Structure
Keep it simple on day one:

api-tests/
├── pom.xml
├── testng.xml
└── src/test/
    ├── java/com/example/tests/
    │   ├── BaseTest.java
    │   ├── TokenManager.java
    │   └── CheckoutTests.java
    └── resources/
        └── config.properties

Enter fullscreen mode Exit fullscreen mode

Step 1: pom.xml

xml<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>api-tests</artifactId>
    <version>1.0</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>5.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>7.10.2</version>
        </dependency>
    </dependencies>
</project>

Enter fullscreen mode Exit fullscreen mode

Step 2: Config File
Under src/test/resources/config.properties:
properties

base.url=https://api-dev.example.com
auth.url=https://auth-dev.example.com/oauth/token
client.id=your-client-id
client.secret=your-client-secret

Enter fullscreen mode Exit fullscreen mode

Tip: don't commit real secrets to git. In a real project, read client.secret from an environment variable instead.

Step 3: BaseTest
Sets the base URL for every test:

javapublic class BaseTest {
    @BeforeSuite
    public void setup() {
        RestAssured.baseURI = "https://api-dev.example.com";
    }
}

Enter fullscreen mode Exit fullscreen mode

Step 4: The Auth Problem
Here's the naive way to handle auth, which most tutorials show:
java// Fetch the token once, reuse forever

String token = given()
    .auth().basic("client", "secret")
    .post("/auth/token")
    .jsonPath().getString("access_token");

Enter fullscreen mode Exit fullscreen mode

This works for 10 tests. It breaks when your suite gets bigger.
The Problem
On one project, our API tokens expired after 15 minutes. Our regression suite took about 22 minutes to run. The first batch of tests passed fine, then around test 140 everything started failing with 401 Unauthorized — not because the code was wrong, but because the token had expired halfway through the run.
The fix isn't to make the suite shorter. The fix is making the framework aware that tokens expire.
The Fix: A Simple TokenManager

java

public class TokenManager {
    private static String token;
    private static Instant expiresAt;

    public static String getToken() {
        if (token == null || Instant.now().isAfter(expiresAt)) {
            refresh();
        }
        return token;
    }

    private static void refresh() {
        Response response = given()
            .formParam("grant_type", "client_credentials")
            .formParam("client_id", "your-client-id")
            .formParam("client_secret", "your-client-secret")
            .post("https://auth-dev.example.com/oauth/token");

        token = response.jsonPath().getString("access_token");
        int expiresIn = response.jsonPath().getInt("expires_in");
        // Refresh 60 seconds early to avoid edge cases
        expiresAt = Instant.now().plusSeconds(expiresIn - 60);
    }
}

Enter fullscreen mode Exit fullscreen mode

Two things worth noting:

The 60-second buffer. If you refresh exactly when the token expires, you can still hit a race condition with the server clock. Refreshing a bit early avoids that.
It only refreshes when needed. Most tests just grab the cached token.

Using It
Every API call pulls a fresh token through TokenManager:
javapublic class CheckoutTests extends BaseTest {

    @Test
    public void getCart_returnsItems() {
        given()
            .header("Authorization", "Bearer " + TokenManager.getToken())
            .pathParam("cartId", "cart-123")
        .when()
            .get("/cart/{cartId}")
        .then()
            .statusCode(200)
            .body("items", hasSize(greaterThan(0)));
    }
}

Enter fullscreen mode Exit fullscreen mode

Step 5: Running It
testng.xml:

xml

<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="API Tests">
    <test name="Checkout">
        <classes>
            <class name="com.example.tests.CheckoutTests"/>
        </classes>
    </test>
</suite>

Enter fullscreen mode Exit fullscreen mode

Run:
bash

mvn test

That's it a working API test suite that doesn't fall over when tokens expire.
What I'd Add Next
This is a starting point, not the finished framework. Once the basics work, I'd add:

Separate config files for dev, staging, and prod
JSON schema validation on responses
An HTML report like Allure or Extent Reports
CI/CD integration with Jenkins or GitHub Actions

The Takeaway
The tricky parts of API automation aren't the tools REST Assured, TestNG, and Maven are straightforward once you've set them up once. The tricky parts are the problems that only show up when a real suite runs against a real API: auth tokens expiring, environment config drift, response schemas changing silently.
If you're setting this up for the first time, start small. Get one test running, handle auth properly, then grow from there.