skip to content

A REST Assured RequestSpecBuilder ignores the RestAssured.baseURI your setup sets - how do you diagnose and fix it?

level: seniorimportance: should knowfreq 42%

answer

  1. the constructor is the only window
  2. copied, not referenced
  3. static field initialiser runs at class load
  4. search for new RequestSpecBuilder(), not the URI
  5. set it on the builder instead

basics

~20 s

new RequestSpecBuilder() copies the RestAssured statics - baseURI, port, basePath, authentication, filters, config, proxy and urlEncodingEnabled - in its constructor, so a builder created before your setup ran keeps the old values. Construct it afterwards, or call setBaseUri directly.

solid answer

~40 s

`new RequestSpecBuilder()` reads the `RestAssured` statics **in its constructor** and copies them into the specification it is assembling: `baseURI`, `port`, `basePath`, `authentication`, the registered filter list, the static `requestSpecification`, `urlEncodingEnabled`, `config` and `proxy`. Nothing re-reads them later — not `build()`, not the request. So a builder constructed before your setup assigns `RestAssured.baseURI` keeps the framework default `http://localhost`, and every call built from it goes to the wrong host. Diagnose by construction order rather than by value: find where `new RequestSpecBuilder()` is written, because a `static final` field initialiser runs at class load, long before any per-suite setup method assigns the static. The fix is ordering (construct the builder after the statics are set) or independence (call `setBaseUri(...)` on the builder and stop leaning on the static at all).

go deeper

for a junior

Remember one fact: a RequestSpecBuilder captures the RestAssured static defaults when it is constructed, not when it is built or used. If setup assigns a static, construct the builder after that line.

for a middle

Be able to list what the constructor captures and explain that the values are copied rather than referenced, so no later assignment reaches an existing builder or the specifications built from it.

for a senior

Diagnose it from construction order without a debugger: locate every new RequestSpecBuilder(), decide whether it sits in a field initialiser or a method body, and reason about class-load timing against setup.

for a principal

Decide the suite-wide convention. Explicit builder setters make each template self-describing and order-insensitive; leaning on the statics centralises the address but makes correctness depend on initialisation timing nobody states in code.

## The symptom A milk-round suite reads the depot address out of configuration in its setup method, assigns it to `RestAssured.baseURI`, and hands every test a `RequestSpecification` built by a `RequestSpecBuilder`. Every call goes to `http://localhost` instead of the depot host, and the failures look like connection refusals or a wall of 404s. Nothing in the test bodies is wrong, and the value of `RestAssured.baseURI` is demonstrably correct if you print it. The specification simply never saw it. ## What the constructor actually copies `new RequestSpecBuilder()` is not an empty container. Its constructor immediately builds the underlying request specification **from the current values of the `RestAssured` statics**, and those values are copied, not referenced: - `RestAssured.baseURI` — defaulting to `http://localhost` - `RestAssured.port` — defaulting to `UNDEFINED_PORT` - `RestAssured.basePath` - `RestAssured.authentication` - the registered filter list from `RestAssured.filters()` - `RestAssured.requestSpecification`, the static default specification, which is merged in - `RestAssured.urlEncodingEnabled` - `RestAssured.config` - `RestAssured.proxy` Nothing re-reads them afterwards. Not `build()`, not the moment the specification is attached to a call, not the request itself. **The window in which the statics matter to a builder is the single line that constructs it.** A builder created before your setup assigns `RestAssured.baseURI` therefore keeps the framework default forever, and so does every specification built from it. ## Why this bites suites specifically The bug is really about initialisation order, and test code has a habit of getting that order wrong in a way application code does not: 1. A `static final RequestSpecification` field runs its initialiser at **class load**, which happens the first time the class is touched — routinely before any per-suite setup method runs. 2. A holder class referenced from a base class or a constant pool gets loaded earlier than the author expects, so "I built it in a helper" does not tell you when it was built. 3. Setup that assigns statics tends to live in a per-suite hook, and the ordering between that hook and an unrelated class's static initialiser is not something the code states anywhere. ## Diagnosing it Diagnose by **construction order, not by value**. Printing `RestAssured.baseURI` proves nothing, because by the time you can print it the copy has already happened. The questions that do resolve it: - Where is `new RequestSpecBuilder()` written, exactly? Search for the constructor, not for the base URI. - Is that line inside a field initialiser, a static block, or a method body? - If it is a field initialiser, what triggers the class load, and does that happen before or after the code that assigns the static? A one-line experiment settles it: construct the builder inside the setup method, immediately after the assignment, and see whether the failures move. If they do, the bug was ordering; if they do not, the address you are reading from configuration is itself wrong and the builder was never the problem. That distinction is worth making explicitly, because the two failures look identical from the outside — every call landing somewhere it should not — and only one of them is fixed by moving a line. ## Two fixes, and which to prefer **Ordering.** Construct the builder after the statics are set — usually by moving the construction into the same setup method, or behind a lazy accessor that is not called until the suite is running. This keeps the static defaults as the single source of the address. **Independence.** Stop relying on the statics for anything the template needs and call `setBaseUri(...)`, `setBasePath(...)`, `setPort(...)`, `setAuth(...)` and `setConfig(...)` on the builder explicitly. The builder then states its own inputs and construction order stops mattering. Independence is the better default for a suite that will be read by people who did not write it: an explicit `setBaseUri` is visible in the file you are looking at, whereas an inherited static is a fact about a different file plus a fact about when it ran. Ordering is the smaller change when a large suite already leans on the statics everywhere and you need the failure gone today. ## The same shape elsewhere The response-side builder has the identical constructor-snapshot behaviour, capturing `RestAssured.rootPath` when it is constructed. So when you audit a suite for this class of bug, the thing to grep for is **every builder construction**, not every base URI — the question is always "what were the statics when this object came into being?", and the answer is fixed at that instant for the life of the object.

  • Which RestAssured statics does the RequestSpecBuilder constructor capture?
    `baseURI`, `port`, `basePath`, `authentication`, the filter list returned by `filters()`, the static `requestSpecification` (which is merged in), `urlEncodingEnabled`, `config` and `proxy`. All of them are read once, at construction, and copied into the specification the builder is assembling.
  • Why does printing RestAssured.baseURI not help you diagnose this?
    Because the value is correct by the time you can print it — the copy happened earlier. The static and the specification are two different pieces of state, and the bug lives in the gap between when the builder was constructed and when the static was assigned. Only construction order answers it.

Constructing the builder is taking a photograph of the RestAssured statics. Everything you change after the shutter closes is missing from the print, however long you wait before developing it.

saying these in an interview costs you the question

  • Assumes the builder reads the statics lazily at build() time
  • Believes the specification re-reads RestAssured.baseURI on each request
  • Debugs by printing the static rather than finding the constructor
  • Thinks assigning the static later will propagate into a built spec
  • Treats it as flakiness because the symptom depends on load order