skip to content

Static Global Defaults

Setting a specification, base URI, auth or filters once as public mutable static fields on one class, and putting them back after. A suite that forgets leaks that state into every later test.

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

questions

4

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
open as a page

In REST Assured, what state does RestAssured.reset() actually put back?

level: middleimportance: must knowfreq 57%

basics

~20 s

RestAssured.reset() restores baseURI, basePath, rootPath, authentication and urlEncodingEnabled to their constants. It nulls requestSpecification, responseSpecification, defaultParser, sessionId and proxy, empties the filter list, drops parser registrations, installs a fresh RestAssuredConfig, and sets port to UNDEFINED_PORT (-1), not 8080.

open as a page

Your REST Assured roster suite passes class by class but fails in a full single-threaded run — how do you find the leaked static state?

level: seniorimportance: must knowfreq 49%

basics

~20 s

Reverse or randomise the class order to confirm the failure follows position, not the test. Then print the RestAssured statics at the boundary, find the class that assigned one, and make it call RestAssured.reset() and re-apply the suite defaults.

open as a page

In REST Assured, how do RestAssured.filters(...) and replaceFiltersWith(...) differ?

level: middleimportance: nice to knowfreq 33%

basics

~20 s

Both register default filters applied to every subsequent request, but RestAssured.filters(...) appends to the existing private static list, while replaceFiltersWith(...) clears the list first and then adds. The no-argument filters() getter returns an unmodifiable view of it.

open as a page