In REST Assured, how do you assert a response cookie's attributes and not only its value?
answer
- no separate detailed assertion method
- the factory takes no arguments
- each call and-composes one property
- unnamed properties stay unchecked
- the extract-side spelling takes a name
basics
~20 sPass a DetailedCookieMatcher into the ordinary cookie call: then().cookie("paddle_session", detailedCookie().value("s-7742a1").maxAge(3600L).secured(true)). There is no separate detailed-cookie assertion method. The factory is a static on RestAssuredMatchers, each call adds one property check, and attributes you never name stay unchecked.
solid answer
~40 sThrough the `cookie(String, DetailedCookieMatcher)` overload — there is no separate detailed-cookie assertion method. `RestAssuredMatchers.detailedCookie()` is a no-argument static factory that returns a combinable matcher over REST Assured's parsed `Cookie`, and each chained call and-composes one property check: `value`, `path`, `domain`, `maxAge`, `secured`, `httpOnly`, `expiryDate`, `version`, `comment` and `sameSite`, each available in a plain-value form and a Hamcrest-matcher form. So `then().cookie("paddle_session", detailedCookie().value(startsWith("s-")).maxAge(3600L).secured(true))` checks three properties at once. Properties you do not name are left unconstrained. Compare that with the weaker forms: `cookie(name)` asserts presence only, and `cookie(name, "s-7742a1")` or `cookie(name, Matcher)` compares the value string while ignoring every attribute. Watch the DSL sides too: `detailedCookie(name)` and `detailedCookies()` are **extract**-side calls that take no matcher and simply hand you `Cookie` and `Cookies` objects to assert on yourself.
code
java · 16 linesimport static io.restassured.RestAssured.given;
import static io.restassured.matcher.RestAssuredMatchers.detailedCookie;
import static org.hamcrest.Matchers.startsWith;
given()
.baseUri("https://api.paddleport.example/v1")
.when()
.post("/sessions/refresh")
.then()
.statusCode(200)
.cookie("paddle_session", detailedCookie()
.value(startsWith("s-"))
.path("/")
.maxAge(3600L)
.secured(true)
.httpOnly(true));go deeper
Know the three shapes of the cookie assertion: name only for presence, name plus value, and name plus a detailed matcher when attributes matter.
Explain that the detailed matcher and-composes one property check per call over the parsed Cookie object, and that unnamed properties stay unconstrained.
Show where an attribute assertion earns its keep - a session endpoint whose scoping quietly regresses - and where over-specifying it makes a test flaky.
Decide which response cookie properties belong in a shared expectation applied across services, and who owns that list when the session mechanism changes.
## The overload you actually call REST Assured has no separate detailed-cookie assertion method. The detailed matcher goes through the ordinary `cookie(...)` call, using the overload `cookie(String cookieName, DetailedCookieMatcher detailedCookieMatcher)` on `ValidatableResponseOptions`: ```java then().cookie("paddle_session", detailedCookie() .value(startsWith("s-")) .path("/") .maxAge(3600L) .secured(true) .httpOnly(true)); ``` `detailedCookie()` is a static factory on `io.restassured.matcher.RestAssuredMatchers` — REST Assured's own matcher class, the same one that carries `matchesXsd`, `matchesDtd` and the `ResponseAwareMatcher` helpers. It takes **no arguments**, and it is the only detailed-cookie entry point on the validate side. ## Three cookie assertions, three strengths | call | what it checks | |---|---| | `cookie("paddle_session")` | the cookie exists; the value is unconstrained | | `cookie("paddle_session", "s-7742a1")` or `cookie(name, Matcher)` | the value only; attributes ignored | | `cookie("paddle_session", detailedCookie()...)` | the parsed `Cookie` object, property by property | - The presence form is `cookie(name)`, which internally matches with `anything()` and fails only when no cookie of that name was set. - The value form takes a literal or any Hamcrest matcher and compares the cookie's value string; a cookie whose attributes changed entirely still passes it. - The detailed form is the only one that can say anything about `Max-Age`, `Path`, `Domain`, `Secure`, `HttpOnly`, `Version`, `Comment`, `Expires` or `SameSite`. ## What `detailedCookie()` builds `DetailedCookieMatcher` is a combinable Hamcrest matcher over REST Assured's `Cookie` type. Each method returns a **new** matcher that and-composes one more property check, so the calls read as a chain but behave as a conjunction. Every property comes in two forms — a plain-value form and a matcher form: - `value(String)` / `value(Matcher<? super String>)` - `path(String)` / `path(Matcher<? super String>)` and `domain(...)` in the same pair - `maxAge(long)` / `maxAge(Matcher<? super Long>)` - `secured(boolean)` / `secured(Matcher<? super Boolean>)` and `httpOnly(...)` in the same pair - `expiryDate(Date)` / `expiryDate(Matcher<? super Date>)` - `version(int)`, `comment(String)` and `sameSite(String)`, each with a matcher form too Two consequences worth internalising. First, **only the properties you name are checked** — the matcher starts from a not-null check on the cookie itself and adds nothing else, so `detailedCookie().secured(true)` says nothing at all about the value. Second, because REST Assured parses the `Set-Cookie` line into a `Cookie` object, the assertion is against parsed properties, not against the raw header text. What each of those attributes instructs a browser to do is HTTP's subject, not the assertion's; the matcher only reports what the service put on the wire. ## The hazard: the extract side spells it differently The names are close enough to swap by accident, and they live on opposite sides of the DSL: 1. Validate side — `cookie(name, DetailedCookieMatcher)`. There is **no** `detailedCookie(name, matcher)` assertion; a Javadoc example once suggested otherwise, and it does not exist. 2. Extract side — `detailedCookie(String name)` returns one `Cookie`, and `detailedCookies()` returns the whole `Cookies` collection. Neither takes a matcher; they hand you objects to assert on yourself. 3. So `detailedCookie()` with empty parentheses is the *matcher factory*, while `detailedCookie(name)` with an argument is an *extraction*. Same word, different job. ## What a failure tells you Because the matcher is a Hamcrest conjunction over the whole `Cookie`, a failure reports the cookie name, the composed description of everything you asked for, and the mismatch: ``` Expected cookie "paddle_session" was not (not null and property 'maxAge' <3600L> and property 'secured' <true>), property 'secured' was <false>. ``` - The mismatch names the offending **property**, so you can see which link of the chain broke rather than only that the cookie was wrong. - If the cookie is absent entirely the mismatch is against `null`, since the matcher opens with a not-null check on the cookie itself. ## When each form is the right one Use presence when the only claim is that a session was established. Use the value form when a test downstream depends on the value's shape. Reach for the detailed form when the cookie's attributes are part of what you are testing — a login endpoint that must keep setting a bounded `Max-Age` and a scoped `Path` is exactly the kind of thing a body assertion can never notice, and exactly the kind of thing that silently regresses when someone rewrites a filter or swaps a session library. - Name the properties whose drift you would actually want to fail a build over, and no more. - Prefer the matcher form of a property over the literal form for anything that legitimately moves: `maxAge(greaterThan(0L))` states the rule, `maxAge(3600L)` pins a number someone will tune. - Over-specifying `expiryDate` on a rolling session turns a good assertion into a flaky one, because the value is computed fresh on every call. - Remember that this assertion reports what the service put on the wire and nothing more; what each attribute instructs a client to do afterwards is a question about HTTP, not about the matcher.
- What does detailedCookie().secured(true) claim about the cookie's value?Nothing. The matcher starts from a not-null check on the cookie and then and-composes only the properties you name, so a chain that mentions `secured` alone constrains that one property. If the value matters too, add `value(...)` explicitly — the detailed form does not fall back to the value comparison the two-argument form performs.
- How do detailedCookie() and detailedCookie(name) differ?They are on opposite sides of the DSL. The no-argument `detailedCookie()` on `RestAssuredMatchers` builds a matcher you pass into `then().cookie(name, matcher)`. The one-argument `detailedCookie(name)` is an extract-side call that returns a single `Cookie` object and takes no matcher at all; `detailedCookies()` returns the whole `Cookies` collection.
saying these in an interview costs you the question
- Looking for a then().detailedCookie(name, matcher) assertion method
- Assuming unnamed attributes are implicitly asserted as absent
- Thinking cookie(name, "value") also checks the cookie's attributes
- Believing the matcher inspects the raw Set-Cookie text rather than parsed properties
- Passing a cookie name into the detailedCookie() matcher factory