In a REST Assured suite, when is relaxedHTTPSValidation() an acceptable choice, and what replaces it?
answer
- removes a control, not a warning
- no authority to trust yet
- trust store plus strictHostnames instead
- certificate scheme makes SSLConfig inert
basics
~20 sOnly where no authority exists to trust: an ephemeral container's self-signed certificate, a local capture proxy, a sandbox you cannot influence. Everywhere else, a trust store with strictHostnames keeps both checks alive and trusts exactly your own issuer.
solid answer
~40 sREST Assured offers three rungs, and only the first removes a control instead of configuring one. `relaxedHTTPSValidation()` skips chain validation and hostname matching together, so it is defensible only where no authority exists to trust — an ephemeral container minting its own certificate, a local capture proxy, a third-party sandbox. The replacement is nearly always `sslConfig().trustStore("bakery-ca.jks", "changeit").strictHostnames()`, which trusts your issuer and still checks the host; build the `SSLConfig` yourself, because the path-and-password shortcuts apply `allowAllHostnames()` for backward compatibility. Where a client key is also required, `auth().certificate(...)` installs a `CertAuthScheme`. Containment matters as much as the choice: keep the relaxed call on one request or specification, never on the static config, and prove any trust setting with a negative test, because nothing in the response records that a check was skipped.
code
java · 16 linesimport io.restassured.RestAssured;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.specification.RequestSpecification;
import static io.restassured.config.SSLConfig.sslConfig;
RequestSpecification trustedBakery = new RequestSpecBuilder()
.setBaseUri("https://orders.bakery.example")
.setConfig(RestAssured.config().sslConfig(
sslConfig().trustStore("bakery-ca.jks", "changeit").strictHostnames()))
.build();
RequestSpecification throwawayBakery = new RequestSpecBuilder()
.setBaseUri("https://orders.bakery.test")
.setRelaxedHTTPSValidation()
.build();go deeper
Know that relaxedHTTPSValidation() exists and what it is for, and that reaching for it should be a question you raise rather than a default you copy from another test.
Be able to compare the three switches and say what each still verifies. Explain why a trust store with strictHostnames is a configuration of trust while relaxed validation is a removal of it.
Show judgement about scope: which specification carries the relaxed call, how you keep it off the static config, and how you prove a trust setting with a negative test rather than assuming it holds.
Own the policy across the suite — which environments may relax validation, who signs that off, how the exception is time-boxed, and how the convention survives new contributors who only see the test that already works.
## The three rungs REST Assured actually offers The library gives you three distinct answers to "this HTTPS call will not connect", and they are not interchangeable. Ranked from weakest to strongest: | Switch | What the client still verifies | Where it belongs | |---|---|---| | `relaxedHTTPSValidation()` | nothing — chain and hostname are both skipped | a disposable host whose certificate you cannot fix | | `sslConfig().trustStore(...).strictHostnames()` | the chain against your own authority, and the hostname | any environment with a private CA | | `auth().certificate(path, password)` | the chain, via a `CertAuthScheme` built from that store | endpoints that also want a client key | Relaxed validation is the only one that removes a control rather than configuring it. Everything else on this list narrows trust; that one deletes it. The distinction matters in a design conversation because the two failures look identical from the outside: a suite with a pinned authority and a suite that trusts everything both go green against a healthy service, and only the second also goes green against an impostor. Nothing in a response body, a status code or an assertion message tells the two apart. ## When it is genuinely acceptable The honest cases are narrow, and an interviewer is listening for whether you can name them without reaching for "it's only tests": - A short-lived container or ephemeral environment that mints a self-signed certificate at start-up, where no authority exists to trust. - A local capture proxy re-signing traffic while you debug one request, removed before the change is committed. - A third-party sandbox that ships a certificate you have no way to import and no way to influence. And the cases where it is not acceptable, however convenient: - Any target that also serves real users or real data, including a shared staging deployment. - A blanket setting in a base class or suite-wide setup, where later tests inherit it invisibly. - A workaround for a certificate that has simply expired, which is a defect worth surfacing rather than hiding. ## What you use instead The replacement is almost always a trust store. `sslConfig().trustStore("bakery-ca.jks", "changeit").strictHostnames()` trusts exactly the authority that issued the bakery pre-order API's certificate and keeps hostname matching alive. Prefer building the `SSLConfig` yourself: the path-and-password shortcuts `RestAssured.trustStore(path, password)` and `given().trustStore(path, password)` finish by applying `allowAllHostnames()` for backward compatibility, so they give you back half the problem you were solving. Where the server also demands a client key, `given().auth().certificate(certURL, password)` installs a `CertAuthScheme` — and here is the detail that catches people: the **two-argument instance form maps its arguments to the trust store**, not to a key store. A client key comes from `CertificateAuthSettings.keyStore(KeyStore)`, or from the five-argument static `RestAssured.certificate(trustStorePath, trustStorePassword, keyStorePath, keyStorePassword, settings)`, which sets both sides. ## The precedence rule that decides which one wins REST Assured applies the `SSLConfig` only when three conditions hold at once: 1. The request URI's scheme is `https`. 2. `sslConfig.isUserConfigured()` is true — an untouched config is skipped. 3. The request's authentication scheme is **not** a `CertAuthScheme`. The third clause is the one that surprises people. If a request uses `auth().certificate(...)`, the carefully built `SSLConfig` beside it is dropped whole — not merged, not partially applied. A team that configures a trust store globally and a client certificate per request will find the trust store simply absent on exactly those requests. Whichever rung you choose, choose one per request and know which one the library will honour. ## Containing the weakest rung The strategic half of this question is blast radius. Relaxed validation leaves no mark: the response looks identical, the assertion output says nothing, and nothing fails. So the containment has to be structural rather than observational: - Keep the call at the request or specification level, never on the static `RestAssured.config`, so a reader of one test can see it. - Give the relaxed target its own `RequestSpecification` with a name that says so, rather than threading a flag through a shared base class. - Treat `useRelaxedHTTPSValidation()` in shared setup as a review finding, the same way you would treat a disabled assertion. - Pair every trust decision with one negative test proving the client rejects the wrong identity; a trust setting nobody has ever seen fail is a setting nobody has verified. The position worth defending is that relaxed validation is a time-boxed exception with a named owner and a route back to a trust store — not a default the suite grows into because it once unblocked a build.
- Why is a globally configured trust store missing on requests that use auth().certificate(...)?REST Assured applies the `SSLConfig` only when the URI is `https`, the config is user-configured, and the authentication scheme is not a `CertAuthScheme`. `auth().certificate(...)` installs exactly that scheme, so the `SSLConfig` is skipped whole rather than merged. Put the trust material into `CertificateAuthSettings` instead on those requests.
- How do you tell from a passing test that relaxed validation was in effect?You cannot. The response, the status code and the assertion output are identical either way, and no warning is emitted. That is why the control has to be structural: keep the call visible at the request or specification level, and add one negative test that fails when the client accepts the wrong identity.
saying these in an interview costs you the question
- Treats relaxed validation as the standard fix for any HTTPS failure
- Puts useRelaxedHTTPSValidation in a shared base class setup
- Argues it is safe because it is only test code
- Uses it to work around an expired certificate instead of reporting it
- Expects a trust store and auth().certificate(...) to combine on one request