In REST Assured, what can then().extract() give you besides a value from the response body?
answer
- the whole round trip, not just the body
- status, headers, cookies, timing, response
- extract side returns values, not matchers
- timeIn takes a TimeUnit
- getList belongs to the path object
basics
~20 sExtraction is not only about body fields. The same ExtractableResponse yields statusCode(), statusLine(), contentType(), header(name), headers(), cookie(name), cookies(), detailedCookie(name), detailedCookies(), sessionId(), time(), timeIn(TimeUnit) and response(), plus whole-body forms such as asString(), asPrettyString(), asByteArray() and asInputStream(). One interface, not several.
solid answer
~50 s`extract()` returns an `ExtractableResponse`, which covers the whole round trip rather than just the body. From it you can read `statusCode()`, `statusLine()` and `contentType()`; `header(name)` and `headers()`; `cookie(name)`, `cookies()`, `detailedCookie(name)` and `detailedCookies()`; `sessionId()`; `time()` in milliseconds and `timeIn(TimeUnit)` converted; and `response()` for the whole `Response` object. On the body side it offers `path(...)`, `jsonPath()`, `xmlPath()`, `htmlPath()`, `as(...)`, and `asString()`, `asPrettyString()`, `asByteArray()` and `asInputStream()`. Watch the two halves of the same word: on the validate side `header(name, matcher)` asserts, while on the extract side `header(name)` returns a `String`. And `getList` is not here at all — it belongs to the path object, as `extract().jsonPath().getList("gainCurve")`. That breadth is why one extraction usually answers several questions about a call: the `Location` header of a newly created fitting, its id and the round-trip time all come off the same object, with no second request.
code
java · 19 linesimport io.restassured.response.ExtractableResponse;
import io.restassured.response.Response;
import static io.restassured.RestAssured.given;
ExtractableResponse<Response> created =
given()
.contentType("application/json")
.body("{\"patientRef\":\"P-4417\"}")
.when()
.post("/fittings")
.then()
.statusCode(201)
.extract();
String location = created.header("Location");
int code = created.statusCode();
long millis = created.time();
String fittingId = created.path("fittingId");go deeper
Be able to name the main things extract() reaches beyond the body: status code, status line, content type, headers, cookies, timing and the whole Response object.
Explain the split between the two sides of then(): the validate side takes matchers and asserts, the extract side takes a name and returns a value. Know that the typed getters live on the path object.
Show judgment about which facet a helper should return - an id, a header, or the whole Response - and why keeping one extraction beats sending the call twice to read two things.
Set the convention for what helpers hand back across a suite, so that reading a header, an id and a timing figure from one call is uniform rather than reinvented in every module.
## `extract()` returns an interface, not a body reader It is easy to read `extract()` as "give me a field", because that is how most examples use it. What it actually returns is an `ExtractableResponse`, and that interface covers the *whole* response — status, headers, cookies, timing and the response object itself — as well as the body. Everything REST Assured knows about the round trip is reachable from that one object, which is why you rarely need to reach past it for anything. ## The roster, grouped by what it answers **Status and content type** - `statusCode()` — the code as an `int` - `statusLine()` — the full status line as a `String` - `contentType()` — the response content type as a `String` **Headers and cookies** - `header(String name)` — that header's value as a plain `String` - `headers()` — a `Headers` object covering all of them - `cookie(String name)` and `cookies()` — cookie values as `String` and as a `Map` - `detailedCookie(String name)` and `detailedCookies()` — the same cookies as `Cookie`/`Cookies`, with their attributes rather than just their values - `sessionId()` — the session cookie's value, under whatever name the session configuration uses **Timing** - `time()` — the round trip in milliseconds - `timeIn(TimeUnit unit)` — the same figure converted to the unit you name **The body** - `path(String, String...)`, `jsonPath()`, `xmlPath()`, `htmlPath()` — read fields through a path engine - `as(...)` — bind the body to a type - `asString()`, `asPrettyString()`, `asByteArray()`, `asInputStream()` — the body whole, in four shapes - `body()` — the body-extraction view on its own **Everything at once** - `response()` — the `Response` object, to hold, pass to a helper, or query later ## The two halves of the same word Several names appear on both sides of `then()`, and they mean different things. On the validate side `header(name, matcher)` *asserts*; on the extract side `header(name)` *returns a value*. The same split runs through cookies and status: | Name | On the validate side | On the extract side | |---|---|---| | `header` | `header("X-Fitting-Revision", equalTo("3"))` asserts | `header("X-Fitting-Revision")` returns a `String` | | `statusCode` | `statusCode(200)` asserts | `statusCode()` returns an `int` | | `cookie` | `cookie("session", matcher)` asserts | `cookie("session")` returns a `String` | | detailed cookies | `cookie(name, DetailedCookieMatcher)` asserts | `detailedCookie(name)` returns a `Cookie` | When you are describing one of these in an interview or a review, name the side. "REST Assured's `extract().header(...)`" is unambiguous; "`header()`" on its own is not. ## What is *not* on the extract side One name trips people up often enough to be worth stating flatly: - `getList(...)` is **not** an `ExtractableResponse` method. The typed collection getters live on the path object, so the chain is `extract().jsonPath().getList("gainCurve")`. - The same applies to `getString`, `getInt`, `getMap` and `getObject` — all of them belong to `JsonPath` or `XmlPath`, reached through `extract().jsonPath()` or `extract().xmlPath()`. - The matcher-taking overloads belong to the validate side; nothing on the extract side accepts a matcher. ## Using it on a fitting API A `POST /fittings` response usually gives you more than one thing worth keeping. From a single extraction you can take the new resource's location, its id and how long the call took: 1. Assert first — `statusCode(201)` and whatever else the value depends on. 2. `extract().header("Location")` for the created resource's URL. 3. `extract().path("fittingId")` for the id a later call will need. 4. `extract().timeIn(TimeUnit.SECONDS)` if you want the round trip in seconds rather than milliseconds — note this is a plain conversion, so a 1,900 ms call reports 1. 5. `extract().response()` when you would rather keep the whole thing and decide later. ## Reading the whole body rather than a field Four methods hand you the body entire, and they differ in more than return type: - `asString()` gives the body as text, decoded with the response's charset. - `asPrettyString()` gives the same text formatted, when the content type is one REST Assured knows how to pretty-print; otherwise it comes back unchanged. - `asByteArray()` gives the raw bytes, which is what you want for a binary attachment such as a stored audiogram file. - `asInputStream()` gives a stream over the same body, for a payload you would rather not hold as one string. The practical takeaway for a newcomer is that extraction is not a body-only feature. When you need the `Location` header of a created fitting, the status code as a value rather than as an assertion, or how long the call took, the answer is on the same interface you already reached — no second request and no separate API. Reach for `response()` only when you genuinely want the whole object; otherwise take the one facet you need and let the rest go.
- What is the difference between extract().time() and extract().timeIn(TimeUnit.SECONDS)?`time()` always reports milliseconds. `timeIn(unit)` reports the same measurement converted to the unit you pass, and the conversion truncates rather than rounds, so a 1,900 ms round trip comes back as 1 second. Use `time()` when you want the raw figure and `timeIn(...)` only when the coarser unit is genuinely what you want to record.
- When would you extract().response() instead of a single value?When one round trip answers several questions, or when a shared helper should let its caller decide what matters. Holding the `Response` lets you read the body, headers and status from one object without sending the request again. The cost is that the object carries no guarantee of its own — whatever you asserted before `extract()` is all the validation it has had.
saying these in an interview costs you the question
- Thinks extract() only reaches the response body
- Calls extract().getList(...) instead of extract().jsonPath().getList(...)
- Expects extract().header(name) to take a Hamcrest matcher
- Confuses extract().statusCode() with the asserting then().statusCode(int)
- Assumes reading headers needs a second request or a filter