REST Assured: the given/when/then chain, two path engines, and a thin README
Java DSL for easy testing of REST services
At a glance
- What is it?
- REST Assured gives Java testers a given/when/then chain for HTTP calls and response assertions, with JsonPath for JSON and XPath for XML. Its README shows only thin examples, so the decisions that actually matter (which version line to sit on, how the two path syntaxes differ, what it leaves undocumented) have to be dug out of the release notes and the wiki.
- Who is it for?
- Adopt REST Assured if your team tests HTTP services from Java and wants assertions in the same language as the code under test; skip it if you need a stubbing layer or POJO mapping as the primary workflow, because neither appears in these examples. Before you pin a version, read the release notes: 6.2.0 contains several non-backward compatible changes, and 6.3.0 deprecates every API that 7.0.0 removes.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Java, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- rest-assured/rest-assured7,151 ★ · +10
| Repository | 2026-09-23 | 2026-11-14 |
|---|---|---|
| rest-assured/rest-assured | 7.1k | 7.2k |
10 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Every verb returns the next object, so tests have no intermediate variables
REST Assured avoids hand-built HTTP plumbing by making each verb return the next object in a chain. `given()` opens the request, links such as `param(...)` extend it, `when()` is where the call actually goes out, and `then()` opens the response side where assertions live. None of the request chains stores an intermediate variable, and that is the point of the design: a request reads as a sequence of named operations instead of a pile of mutable builder objects.
given().
param("key1", "value1").
param("key2", "value2").
when().
post("/somewhere").
then().
body(containsString("OK"));What that costs you shows up in a test that mixes query parameters, authentication and body checks at once. There is no example of parking a half-built request in a variable, so a long scenario becomes one tall vertical chain, and any conditional logic around the request has to wrap the whole chain rather than a single link.
body() takes a path expression and a matcher, and nothing else is configured
An assertion here is a path expression plus a matcher. A single JSON field is one line, with the document root implied:
get("/lotto").then().assertThat().body("lotto.lottoId", equalTo(5));Reaching into a nested collection works the same way, and `hasItems` matches on membership rather than on position, so a response that returns winner ids in a different order still passes:
get("/lotto").then().assertThat().body("lotto.winners.winnerId", hasItems(23, 54));Notice what is absent from both chains. There is no base URI, port, header setup or timeout anywhere in these examples, so every connection setting has to come from a place the README does not cover. The path expression is doing all the work you would normally split between a client configuration object and an assertion helper.
hasXPath is marked XML only, so assertions bind you to one payload format
The same `body(...)` call has a different syntax depending on the response format. For XML the matcher is `hasXPath` and the argument is an XPath expression, and this form is labelled XML only:
given().
params("firstName", "John", "lastName", "Doe").
when().
post("/greetMe").
then().
body(hasXPath("/greeting/firstName[text()='John']"));Text responses take a third route, `containsString("OK")`, with no path at all. The path-plus-matcher form is not limited the same way: the README introduces its first example as validating "the JSON or XML response".
from() hands back a List for JSON and a DOM Node for XML, and no POJO
When you want the value rather than a verdict, the response is turned into a string and passed to `from(...)`. JsonPath returns plain Java collections:
// Example with JsonPath
String json = get("/lotto").asString();
List<String> winnerIds = from(json).get("lotto.winners.winnerId");
// Example with XmlPath
String xml = post("/shopping").andReturn().body().asString();
Node category = from(xml).get("shopping.category[0]");The two engines hand back different types, a `List<String>` for JSON and a DOM `Node` for XML, so a shared helper cannot treat them alike without branching. More important: the README does not document mapping a response onto your own POJO classes, and it does not document serializer or deserializer configuration either. If your suite asserts on domain objects rather than paths, that part of the workflow has to come from the Usage guide in the wiki, not from here.
auth().basic() is a link in the chain, but method coverage stops at seven verbs
Authentication is another link in the same chain, so credentials do not need a separate client object:
given().auth().basic(username, password).when().get("/secured").then().statusCode(200);Method coverage is asymmetric in a way worth planning around. Any HTTP method is said to work, but POST, GET, PUT, DELETE, OPTIONS, PATCH and HEAD are the ones named as explicitly supported, and the things you can specify and validate are listed as parameters, headers, cookies and the body. Anything outside that list is simply not covered by these examples: form parameters, multipart uploads, proxies, redirects and connection pooling all need the wiki. The tests you write first will fit inside the narrow band these snippets describe; the fifth one probably will not.
No Maven snippet exists, so the coordinates come from the artifact page
There is no install command to copy. No Maven or Gradle snippet appears anywhere in the README, so nothing here can be pasted into a pom without filling in the coordinates yourself. What the project offers instead is the artifact page for io.rest-assured on Maven Central and a Getting started page in its wiki. Two version facts decide what you download: version 6.2.0 made the `rest-assured` module pure Java with no direct Groovy dependency, and the newest release named in the news entries is 6.3.0.
The first working call is one line, and the README does not say where its base URI comes from:
get("/lotto").then().assertThat().body("lotto.lottoId", equalTo(5));Read that as the shape of every test rather than a complete program. The repository root explains why there is no single jar to point at: `json-path/` and `xml-path/` are separate modules, `rest-assured-common/` and `rest-assured-bom/` sit beside them, and `rest-assured-all/` and `modules/` are separate directories with their own jobs.
No releases page, two supported lines, and docs scattered across wiki and Javadoc
The GitHub repository carries no releases page, so version history lives in two places: the news list at the top of the README and changelog.txt in the repository root. Documentation is split the same way, with the Getting started, Usage, Release Notes and FAQ pages living in the wiki and a separate Usage_Legacy path kept for the older style. The Javadoc links are all pinned to 6.2.0, one release behind the newest 6.3.0.
The upgrade path is the real trap. 6.2.0 contains several non-backward compatible changes, so its release notes come before upgrading, and 6.3.0 prepares for 7.0.0, which drops Apache HttpClient 4 and Groovy from the default dependencies; every API 7.0.0 removes already has a replacement, and the new `rest-assured-openrewrite` module has a recipe that moves your code over.
What none of this gives you is a dependency list, a compatibility matrix, or a plain description of what changed in a given release beyond a link. The last push was on 2026-10-30, the licence is Apache-2.0, and the release plumbing is three shell scripts in the repository root: mvn_release.sh, generate_javadoc.sh and update_wiki.sh.
Editorial conclusion
Adopt REST Assured if your team tests HTTP services from Java and wants assertions in the same language as the code under test; skip it if you need a stubbing layer or POJO mapping as the primary workflow, because neither appears in these examples. Before you pin a version, read the release notes: 6.2.0 contains several non-backward compatible changes, and 6.3.0 deprecates every API that 7.0.0 removes. The last push was on 2026-10-30 and the licence is Apache-2.0.
Frequently asked questions
How do I use REST Assured?
REST Assured is a Java DSL in which every verb returns the next object in a chain: given() sets up the request, when() sends it, and then() exposes the response for assertions. The shortest example asserts a single JSON field with equalTo.
Can REST Assured be used for API testing?
That is its stated purpose: testing and validation of REST services, which the project says is harder in Java than in dynamic languages such as Ruby and Groovy. Any HTTP method is said to work, with POST, GET, PUT, DELETE, OPTIONS, PATCH and HEAD named as explicitly supported, covering parameters, headers, cookies and the body.
How do you install REST Assured?
The README carries no Maven or Gradle snippet, so there is nothing to copy into a pom. It points at the io.rest-assured artifact on Maven Central and at a Getting started page in the project wiki, and the newest release named in its news list is 6.3.0.
How is RequestSpecification used in REST Assured?
The README never names RequestSpecification. It shows the request side as the chain starting at given(), where each link returns the next object and auth().basic() attaches credentials to it, so the specification is expressed as the chain rather than as a variable you hold.
Can REST Assured map a response to a POJO class?
The README does not document POJO mapping. Its parsing examples return plain Java values: a String from asString(), a List<String> from from(json).get("lotto.winners.winnerId"), and a DOM Node from from(xml).get("shopping.category[0]").
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/rest-assured-rest-assured)Star history chart for your README
[](https://hysenlabs.com/projects/rest-assured-rest-assured)Was this useful?