In REST Assured, which querier getters show a spec's path placeholders and their values?
answer
- two getters for braces, four for values
- undefined means still owed a value
- named versus positional are separate maps
- getDerivedPath substitutes what it knows
basics
~20 sREST Assured's QueryableRequestSpecification names every brace in a path with getPathParamPlaceholders and only the unfilled ones with getUndefinedPathParamPlaceholders. The values come back from getPathParams, getNamedPathParams, getUnnamedPathParams and getUnnamedPathParamValues, and getDerivedPath shows the path with known values applied.
solid answer
~50 sTwo getters describe the template and four describe the values. `getPathParamPlaceholders()` lists every placeholder in the path REST Assured will request — base URI path, base path and the verb's path combined — while `getUndefinedPathParamPlaceholders()` applies what it has and lists only what is still missing. On the value side, `getNamedPathParams()` holds values set with `pathParam(name, value)`, `getUnnamedPathParams()` pairs positional values with the placeholders they filled, `getUnnamedPathParamValues()` returns the raw positional list, and `getPathParams()` is the combined summary. `getUserDefinedPath()` shows the template as written and `getDerivedPath()` shows it with known values substituted, so an unfilled `{ventId}` is still visible in it. Everything comes back unmodifiable, which makes this a read-only pre-flight check: a greenhouse specification factory can assert that after it runs the spec still owes exactly one value, `ventId`, turning a late and confusing request failure into an immediate named test failure.
code
java · 14 linesRequestSpecification zoneSpec = new RequestSpecBuilder()
.setBaseUri("https://climate.greenhouse.test")
.setBasePath("/api/v2/zones/{zoneId}/vents/{ventId}")
.addPathParam("zoneId", "z-17")
.build();
QueryableRequestSpecification q = SpecificationQuerier.query(zoneSpec);
q.getPathParamPlaceholders(); // [zoneId, ventId]
q.getUndefinedPathParamPlaceholders(); // [ventId]
q.getNamedPathParams().get("zoneId"); // "z-17"
q.getUnnamedPathParamValues(); // [] - nothing positional was supplied
q.getPathParams(); // {zoneId=z-17}
q.getDerivedPath(); // "/api/v2/zones/z-17/vents/{ventId}"go deeper
Learn the pairing: getPathParamPlaceholders for every brace in the path, getUndefinedPathParamPlaceholders for the ones still missing a value, and getNamedPathParams for the values you supplied by name.
Explain why the placeholder scan covers the base path as well as the verb's path, and why named and positional values are kept in separate getters rather than merged into one map.
Use the read-back as a pre-flight check in a specification factory, so a spec that still owes a path value fails a fast object-level test instead of a confusing request later in a long run.
Decide how much of a path a shared specification should pin at all. Pinning the site and leaving the resource id to the call is a contract worth stating, and worth asserting with these getters.
## Placeholders and values are two different questions A REST Assured path such as `/api/v2/zones/{zoneId}/vents/{ventId}` has two things worth asking about. *Which braces are in it?* and *which of them have a value?* `QueryableRequestSpecification` answers them with two different families of getters, and mixing the families up is where most confusion starts. | Question | Getter | |---|---| | Which placeholders exist at all? | `getPathParamPlaceholders()` | | Which placeholders are still unfilled? | `getUndefinedPathParamPlaceholders()` | | Which named values were supplied? | `getNamedPathParams()` | | Which positional values were supplied? | `getUnnamedPathParams()`, `getUnnamedPathParamValues()` | | All supplied values together | `getPathParams()` | | What does the path look like now? | `getUserDefinedPath()`, `getDerivedPath()` | ## The two placeholder lists Both scan the path REST Assured will actually request — the path from the base URI, plus the base path, plus the path handed to the verb — so placeholders written into `setBasePath(...)` are found just as readily as ones written into `get("/zones/{zoneId}")`. - `getPathParamPlaceholders()` returns every placeholder name in that path, whether or not a value exists for it. Think of it as the shape of the template. - `getUndefinedPathParamPlaceholders()` first applies the values it has, then lists what is left. On the greenhouse specification above with `zoneId` supplied, it returns just `ventId`. The difference between the two lists is exactly the set of values you still owe the request, which makes it the natural thing for a specification factory to assert before it hands the spec out. ## The four value getters - `getNamedPathParams()` — values supplied by name, through `pathParam(name, value)`, `pathParams(Map)` or `RequestSpecBuilder.addPathParam(...)`. - `getUnnamedPathParams()` — positional values paired with the placeholder each one filled. The pairing only exists where a value actually matched a placeholder, so an extra positional value has no entry here. - `getUnnamedPathParamValues()` — the raw positional values as a list, with no pairing attempted. This is what you read when you want to know what was passed rather than where it landed. - `getPathParams()` — the named values plus the unnamed ones whose keys do not collide with a named key, in one map. It is the convenient summary; the other three are the precise answers. All four come back through `Collections.unmodifiableMap` or `unmodifiableList`, so they are for reading only. ## What the path getters show Two more getters make the picture concrete rather than abstract: - `getUserDefinedPath()` returns the path as it was written, placeholders intact — the template. - `getDerivedPath()` returns the same path with the values that are known already substituted in, so an unfilled placeholder is still visible in the middle of it. On the greenhouse specification that is `/api/v2/zones/z-17/vents/{ventId}`, which shows the state of the request at a glance. Both reflect the path the verb supplied, which is empty until a verb has been called; placeholders living in the base path still appear in `getPathParamPlaceholders()` regardless. ## Where you use this The realistic use is a guard on a shared specification or a factory method. A greenhouse climate suite that builds `zoneSpec` centrally can assert that after the factory runs the specification still owes exactly one value, `ventId`, and that `zoneId` is already pinned to the site under test. That is a cheap object-level check with no server behind it, and it turns a class of late, confusing request failures into an immediate, named test failure. The same read-back is what you reach for when a merged specification appears to have lost a path value: compare `getNamedPathParams()` with `getPathParamPlaceholders()` and the gap names itself. ## Choosing which getter to reach for The getters look interchangeable and are not. A short decision list keeps them straight: - Asking *is this specification complete?* — subtract nothing, just check that `getUndefinedPathParamPlaceholders()` is empty. - Asking *did my factory pin the right zone?* — read `getNamedPathParams().get("zoneId")`, which answers about the named value specifically rather than about the path as a whole. - Asking *what will this request address?* — read `getDerivedPath()`, or `getURI()` if you want the host and query string with it. - Asking *what template was written?* — read `getUserDefinedPath()`, which never substitutes anything. ## A note on mutability Every map and list on this family of getters is wrapped before it is returned, so a missing value cannot be supplied by writing into the result. Adding one goes back through the specification — `pathParam(name, value)`, `pathParams(Map)` or the builder's `addPathParam(...)` — and removing one goes through `removeNamedPathParam`, `removePathParam` or `removeUnnamedPathParam` on `FilterableRequestSpecification`. The read side and the write side are deliberately separate interfaces, and holding that distinction in mind is most of what it takes to use these getters without surprise.
- What is the difference between getPathParamPlaceholders and getUndefinedPathParamPlaceholders?The first lists every placeholder in the path, filled or not — the shape of the template. The second substitutes the values the specification already holds and lists only what remains. The difference between the two lists is precisely the set of values the request still owes.
- Why are named and positional path values exposed through separate getters?Because they are supplied differently and pair differently. Named values come from `pathParam(name, value)` and are keyed by name; positional values arrive as an ordered list and are matched to placeholders only where a match exists. `getUnnamedPathParamValues()` returns the raw list, `getUnnamedPathParams()` the pairing, and `getPathParams()` a combined view.
saying these in an interview costs you the question
- Thinks getPathParamPlaceholders only lists unfilled placeholders
- Expects placeholders written into the base path to be ignored
- Treats named and positional path values as one map
- Assumes getDerivedPath removes placeholders it cannot fill
- Tries to add a missing value through the returned map