skip to content

In REST Assured, which suite-wide defaults do you set as statics on the RestAssured class?

level: juniorimportance: must knowfreq 71%

answer

  1. one class, whole JVM
  2. public fields, not a builder
  3. filters go through a method
  4. read fresh on every given()
  5. reset() is the undo

basics

~20 s

REST Assured keeps suite-wide defaults as public static fields on its RestAssured class: baseURI, port, basePath, authentication, config, requestSpecification, responseSpecification, rootPath, urlEncodingEnabled, defaultParser, sessionId and proxy. Default filters are registered through the static filters method instead.

solid answer

~50 s

`io.restassured.RestAssured` is the process-wide entry point, and most of its suite-wide defaults are plain **public mutable static fields**: `baseURI`, `port`, `basePath`, `authentication`, `config`, `requestSpecification`, `responseSpecification`, `rootPath`, `urlEncodingEnabled`, `defaultParser`, `sessionId` and `proxy`. You assign them directly — `RestAssured.baseURI = "https://roster.belltower.test"` — and every later `given()` picks them up, because `given()` builds a brand-new request specification out of those fields on each call. Filters are the one exception: the backing list is **private**, so you register through `RestAssured.filters(...)`, which *appends*, or `RestAssured.replaceFiltersWith(...)`, which clears first; the no-argument `RestAssured.filters()` returns an unmodifiable view. Because this is a single static holder shared by the whole JVM and nothing scopes an assignment to a test, whatever the last test assigned is what the next test inherits — so assign the statics in exactly one place for the run, and pair any class that deviates with a `RestAssured.reset()` in its teardown.

code

java · 20 lines
java
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.greaterThan;
import io.restassured.filter.log.ErrorLoggingFilter;

// one place, once, for the whole run
RestAssured.baseURI = "https://roster.belltower.test";
RestAssured.basePath = "/api/v2";
RestAssured.replaceFiltersWith(new ErrorLoggingFilter());

// every later call inherits them
given()
    .queryParam("band", "sunday")
.when()
    .get("/towers/st-cuthberts/ringers")
.then()
    .statusCode(200)
    .body("ringers.size()", greaterThan(6));

// hand the JVM back to the next class
RestAssured.reset();

go deeper

for a junior

Be ready to name the common statics — baseURI, basePath, port, authentication, requestSpecification — and to say that they live on the RestAssured class and apply to every subsequent request in the JVM.

for a middle

Explain that given() builds a fresh specification from the statics on every call, that the filter list is private and reached through filters() and replaceFiltersWith(), and that RequestSpecBuilder snapshots the statics in its constructor.

for a senior

Show the operating discipline: one assignment point for the whole run, reset() in teardown for any class that deviates, and a review habit of challenging new global assignments before they reach master.

for a principal

Own the tradeoff. A static entry surface is cheap to adopt and impossible to scope, so decide deliberately whether your suite treats it as read-only after startup and pushes all variation into specifications the tests hold themselves.

`io.restassured.RestAssured` is REST Assured's static entry point. It is the class you `import static` to reach `given()`, `when()`, `get()` and the rest of the DSL, and it is also where the library parks the settings that should apply to *every* request the JVM makes. Those settings are ordinary **public mutable static fields** — not a builder, not a properties file. That shape is the whole story of this topic: it is what makes them convenient, and it is what makes them leak. ## The fields you assign directly | Static | Type | Default | What it seeds | |---|---|---|---| | `baseURI` | `String` | `"http://localhost"` (`DEFAULT_URI`) | scheme and host for every request | | `port` | `int` | `-1` (`UNDEFINED_PORT`) | an explicit port, when one is wanted | | `basePath` | `String` | `""` (`DEFAULT_PATH`) | a prefix in front of every path | | `authentication` | `AuthenticationScheme` | `NoAuthScheme` (`DEFAULT_AUTH`) | the default credentials | | `config` | `RestAssuredConfig` | a fresh instance | the eighteen config objects | | `requestSpecification` | `RequestSpecification` | `null` | a specification applied to every request | | `responseSpecification` | `ResponseSpecification` | `null` | expectations applied to every `then()` | | `rootPath` | `String` | `""` (`DEFAULT_BODY_ROOT_PATH`) | the body root path | | `urlEncodingEnabled` | `boolean` | `true` (`DEFAULT_URL_ENCODING_ENABLED`) | whether the library encodes for you | | `defaultParser` | `Parser` | `null` | how to parse a body with no usable content type | | `sessionId` | `String` | `null` (`DEFAULT_SESSION_ID_VALUE`) | a session id put on every request | | `proxy` | `ProxySpecification` | `null` | the proxy every request travels through | For a bell-tower roster suite, three assignments in one place replace three lines in every test: ```java RestAssured.baseURI = "https://roster.belltower.test"; RestAssured.basePath = "/api/v2"; RestAssured.urlEncodingEnabled = true; ``` ## Filters are the exception The default filter list is not a public field. It is `private static List<Filter> filters`, reached only through methods: - `RestAssured.filters(List<Filter>)` and `RestAssured.filters(Filter, Filter...)` **add** to the list. - `RestAssured.replaceFiltersWith(List<Filter>)` and `replaceFiltersWith(Filter, Filter...)` clear the list first, then add. - `RestAssured.filters()` with no arguments is the getter and returns `Collections.unmodifiableList(...)` — useful for asserting in teardown that nothing was left behind. - Nothing de-duplicates the list, so registering the same filter twice really does run it twice. ## When the values are read `RestAssured.given()` (and `expect()`, and the shorthand `get("/x")`, which delegates to `given()`) calls an internal `createTestSpecification()`. That method constructs a **fresh** `RequestSpecificationImpl` out of `baseURI`, `port`, `basePath`, `authentication`, the filter list, `requestSpecification`, `urlEncodingEnabled`, the current config and `proxy` — every single time. Three consequences follow: 1. Assigning a static between two tests changes the second test and only the second test. 2. A request already part-way through its chain never sees a later assignment. 3. There is no "apply" step and no ordering subtlety at the call site; the read is the call. The builders behave differently, and this catches people. `new RequestSpecBuilder()` **snapshots** the same statics in its constructor, and `new ResponseSpecBuilder()` snapshots `rootPath`. A builder created in a field initialiser, before your setup code assigns `RestAssured.baseURI`, keeps the old value for the life of the object. ## The price of a mutable global Everything above describes convenience. The bill arrives the first time two test classes disagree: - The state is **JVM-wide**, so it crosses class boundaries, package boundaries and any grouping your runner imposes. - Nothing scopes an assignment to a test. Assigning `RestAssured.basePath = "/api/v1"` in one class silently retargets every later class in the same run. - The failure it produces is **order dependent**: the class fails in a full run and passes alone, which is the single most expensive kind of red build to chase. - The statics are readable as well as writable, so a teardown assertion or a printed line at the boundary is cheap diagnosis. ## Putting them back `RestAssured.reset()` is the library's own undo. It restores `baseURI`, `basePath`, `rootPath`, `authentication` and `urlEncodingEnabled` to their constants; nulls `requestSpecification`, `responseSpecification`, `defaultParser`, `sessionId` and `proxy`; empties the filter list; discards parser registrations; installs a fresh `RestAssuredConfig`; and sets `port` back to `UNDEFINED_PORT` (`-1`). The discipline that keeps a suite honest is small: - Assign the statics in exactly one place for the whole run, never per class. - If a class must deviate, prefer a per-request setting or a `RequestSpecification` it owns. - If a class genuinely has to touch a static, call `RestAssured.reset()` in its teardown and re-apply the suite defaults. - Treat a global assignment in a pull request as something to justify, not something to wave through.

  • Why is the default filter list not a public static field like baseURI is?
    It is `private static List<Filter> filters`, so REST Assured can control how it changes: `filters(...)` appends, `replaceFiltersWith(...)` clears then appends, and the no-argument `filters()` hands back an unmodifiable view rather than the live list. A public `List` field would let any test mutate or null it, and would make the append-versus-replace distinction impossible to express.
  • If a RequestSpecBuilder is created before you assign RestAssured.baseURI, what does it use?
    The old value. `new RequestSpecBuilder()` snapshots `baseURI`, `port`, `basePath`, `authentication`, the filter list, `requestSpecification`, `urlEncodingEnabled`, config and `proxy` in its constructor, so it is frozen at construction time. `new ResponseSpecBuilder()` snapshots `rootPath` the same way. Build the specification after the statics are set, or set them on the builder explicitly.

saying these in an interview costs you the question

  • Thinks the statics are scoped to one test class
  • Believes given() caches the statics after the first call
  • Assigns RestAssured.filters directly as if it were public
  • Expects RestAssured.filters(...) to replace the existing list
  • Never resets, then blames the server for flaky runs