skip to content

Log Detail Selection

Choosing what is printed and where it lands: the calls shared by both sides, the four that exist only on the request, the four only on the response, and the stream underneath.

part ofREST Assuredoverview, primer and where to startread it →
on this pageshow

questions

3

In REST Assured, which log() calls narrow the output to just the headers, cookies or body?

level: juniorimportance: must knowfreq 64%

answer

  1. two log specs, not one
  2. six shared calls, four per side
  3. method, uri, params are request-only
  4. status and ifError are response-only
  5. each log() call adds its own filter

basics

~20 s

REST Assured narrows log output instead of printing everything: body(), headers() and cookies() exist on both sides, method(), uri() and params() only on the request, status() only on the response. Each call registers its own logging filter.

solid answer

~50 s

`given().log()` and `then().log()` both return a log spec, and neither is limited to `all()`. Six calls are shared: `body()`, `headers()`, `cookies()`, `all()`, `everything()` and `ifValidationFails()`. Four exist only on the request spec — `method()`, `uri()`, `params()` and its alias `parameters()`. Four exist only on the response — `status()`, `ifError()`, `ifStatusCodeIsEqualTo(int)` and `ifStatusCodeMatches(Matcher)`. So on a seed-bank call, `given().log().uri().log().params()` prints the resolved URI plus every query, form and path parameter, while `then().log().status()` prints the status line only. Each `log().x()` registers a separate `RequestLoggingFilter` or `ResponseLoggingFilter` on the spec, so chaining two calls produces two printed blocks rather than one merged one, and `given().log().status()` simply does not compile. `all()` is the union on its own side — the request block prints method, URI, parameters, headers, cookies and body; the response block prints the status line, headers and body. Narrow when you only need one of them.

code

java · 14 lines
java
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.equalTo;

given()
    .log().method()
    .log().uri()
    .pathParam("accessionId", "SB-2291")
.when()
    .get("/seed-bank/accessions/{accessionId}")
.then()
    .log().status()
    .log().body()
    .statusCode(200)
    .body("taxon", equalTo("Silene stenophylla"));

go deeper

for a junior

Be ready to name the narrowing calls without looking them up: body, headers and cookies on both sides, method, uri and params on the request, status on the response. Knowing that all() exists is not enough.

for a middle

Explain that each log() call registers a separate logging filter rather than setting a flag, so two calls print two blocks in registration order and nothing merges or de-duplicates them.

for a senior

Show judgment about volume: say which calls you leave on for every case in CI and which you reserve for the cases whose payload you assert, and why printing whole bodies everywhere hurts a real suite.

for a principal

Own the convention. Decide once, for the whole suite, what every call prints by default, so log output is uniform across hundreds of cases and no individual test has to invent its own diagnostics.

## Why `log().all()` is only the widest option REST Assured's printed diagnostics are reached through a `log()` call on either side of the DSL, and `log()` returns a small specification object rather than printing anything itself. `given().log()` returns a `RequestLogSpecification`; `then().log()` returns a `ValidatableResponseLogSpec`, and `expect().log()` or a `ResponseSpecification`'s own `log()` returns a `ResponseLogSpecification`. Every one of them offers `all()` — but `all()` is just the widest member of a family, and the family exists precisely so a suite can print one part of a message instead of the whole thing. ## The six calls both sides share - `body()` — the payload only, with a `body(boolean shouldPrettyPrint)` overload. - `headers()` — the header block only. - `cookies()` — the cookie block only. - `all()` — everything that side is able to print, with an `all(boolean)` overload. - `everything()` — an alias that delegates straight to `all()`. - `ifValidationFails()` — the conditional form, a subject of its own. ## The four that exist only on the request, and the four only on the response | Call | Side | Prints | |---|---|---| | `method()` | request only | `Request method: POST` | | `uri()` | request only | `Request URI:` plus the fully resolved URL | | `params()` / `parameters()` | request only | request, query, form and path parameters, plus multipart parts | | `status()` | response only | the status line, e.g. `HTTP/1.1 404 Not Found` | | `ifError()` | response only | the whole response when the status code is 400 or above | | `ifStatusCodeIsEqualTo(int)` | response only | the whole response for one exact status code | | `ifStatusCodeMatches(Matcher)` | response only | the whole response when a Hamcrest matcher accepts the code | `then().log().params()` and `given().log().status()` are not typos you can get away with: the methods are simply absent from the interface on that side, so the compiler rejects them. ## Each call registers its own filter Narrowing is not a flag on a single printer. Every `log().x()` call builds a logging filter and adds it to the request specification: - `given().log().method()` registers a `RequestLoggingFilter` carrying `LogDetail.METHOD`. - `then().log().status()` registers a response logging filter carrying `LogDetail.STATUS`. - Two calls therefore register two filters and produce two printed blocks, in registration order. - Nothing merges or de-duplicates them, so `given().log().all().log().body()` prints the body twice. The request filter prints before the request goes out; the response filters print after the response comes back. That ordering is why a request block always appears above its response block even when the two `log()` calls sit next to each other in the source. ## Narrowing a seed-bank suite Take a suite that reads `GET /seed-bank/accessions/{accessionId}` and asserts on `taxon` and `germinationRate`. Printing `log().all()` on both sides of every case buries CI output under inventory payloads that can run to thousands of accessions. A more useful shape is: 1. Print `given().log().uri()` on every case, so a failure names the exact URL that was hit. 2. Print `then().log().status()` on every case, so an unexpected `503` is visible without a body. 3. Reach for `then().log().body()` only on the cases whose payload you actually assert. 4. Keep `given().log().params()` for the search endpoints, where the query parameters are the thing under test. `params()` is worth singling out: it prints four separate maps — request parameters, query parameters, form parameters and path parameters — and the multipart parts as well, so it is the one call that shows a placeholder such as `{accessionId}` beside the value that filled it. ## Reading what came out The request block is a set of labelled lines: `Request method:`, `Request URI:`, then the parameter maps, the headers, the cookies and the body, each written only if the chosen detail covers it. A `Proxy:` line appears under `all()` alone. The response block starts with the status line, then the headers, then the body, pretty-printed by default when the content type is JSON or XML. Choosing a narrower call does not change any of those labels; it only decides which of them are written at all. That is the whole point of the family: the labels stay stable so a reader always recognises the block, while the volume is yours to choose per call.

  • Which REST Assured log call prints a request's path parameters, and what else appears in that block?
    `given().log().params()`, or its alias `parameters()`. The block prints four maps — request parameters, query parameters, form parameters and path parameters — plus any multipart parts. `given().log().all()` includes the same block. There is no response-side equivalent, because a response has no parameters of its own.
  • What exactly does then().log().status() write for a response to a missing seed-bank accession?
    The full status line taken from the response — for example `HTTP/1.1 404 Not Found` — not the bare integer. `then().log().all()` prints that same line first and then the headers and the body, so `status()` is simply the first slice of the wider block.

saying these in an interview costs you the question

  • Thinks log().all() is the only option available
  • Calls then().log().params() to see query parameters
  • Expects given().log().status() to print the response code
  • Believes chaining two log() calls merges them into one block
  • Assumes then().log().status() prints only the number, not the status line
open as a page

In REST Assured, why is there no then().log().params() or given().log().status()?

level: middleimportance: should knowfreq 42%

basics

~20 s

REST Assured's LogDetail is side-specific: PARAMS, METHOD and URI describe only a request, STATUS only a response. Each log spec declares only the calls its side can print, and the logging filters throw IllegalArgumentException when a wrong value reaches them.

open as a page

In REST Assured, you set LogConfig.defaultStream() but log() still prints to System.out. Why?

level: seniorimportance: nice to knowfreq 31%

basics

~20 s

REST Assured resolves the print stream when log() is called, not when the request is sent. A config() applied after log() in the chain arrives too late, so the already-registered logging filter still holds System.out. Set the config first.

open as a page