How can I avoid RestAssured to multiply my request params when using RequestSpecification?
Hello, all! I confess I did some research on this issue, but didn't find anything substancial on the topic to solve my problem.
I have a global configuration for all my tests, that I'm setting in a @BeforeAll tag using JUnit 5, as you can see below:
// Build request specification
RequestSpecification requestSpec = new RequestSpecBuilder()
.setBaseUri(EnvironmentConfig.get("base.url"))
.addHeaders(getHeaders())
.addHeader("Authorization", "Bearer " + getKeycloakToken())
.setUrlEncodingEnabled(false)
.setConfig(config()
.objectMapperConfig(
io.restassured.config.ObjectMapperConfig.objectMapperConfig()
.defaultObjectMapperType(ObjectMapperType.JACKSON_2)
.jackson2ObjectMapperFactory((cls, charset) -> objectMapper)
)
.encoderConfig(
encoderConfig().appendDefaultContentCharsetToContentTypeIfUndefined(false)
))
.build();The headers should be the same for all requests, so I coded a sendRequest method that does what follows:
public Response executeRequest(RequestParameters requestParameters, RequestSpecification specification) {
if (requestParameters.getQueryParams() != null) {
prepareRequestQueryParams(requestParameters, specification);
}
if (requestParameters.getBody() != null) {
prepareRequestBody(requestParameters, specification);
}
if (requestParameters.getPathParams() != null && !requestParameters.getPathParams().isEmpty()) {
for (Map.Entry<String, String> entry : requestParameters.getPathParams().entrySet()) {
System.out.println("key: " + entry.getKey() + "value: " + entry.getValue());
specification.pathParam(entry.getKey(), entry.getValue());
}
}
//TO DO: Remover quando a API estiver deployada no Gateway
RestAssured.useRelaxedHTTPSValidation();
specification.log().all();
Response response = switch (requestParameters.getMethod()) {
case Method.GET ->
requestParameters.getEndpoint() != null ? specification.when().get(requestParameters.getEndpoint()) : specification.when().get();
case Method.POST ->
requestParameters.getEndpoint() != null ? specification.when().post(requestParameters.getEndpoint()) : specification.when().post();
case Method.PUT ->
requestParameters.getEndpoint() != null ? specification.when().put(requestParameters.getEndpoint()) : specification.when().put();
case Method.PATCH ->
requestParameters.getEndpoint() != null ? specification.when().patch(requestParameters.getEndpoint()) : specification.when().patch();
case Method.DELETE ->
requestParameters.getEndpoint() != null ? specification.when().delete(requestParameters.getEndpoint()) : specification.when().delete();
default -> throw new IllegalArgumentException("Unsupported HTTP method: " + requestParameters.getMethod());
};
response.then().log().all();
return response;
}As you can see, I'm sending the RequestSpecification as one of the method input parameters, because, beyond the global RequestSpecification, I have another one to generate the KeyCloak token. The first problem is... when the tests are run, I get the following exception from this method:
Before All/After All failed
java.lang.NullPointerException: Cannot invoke method log() on null object
at org.codehaus.groovy.runtime.NullObject.invokeMethod(NullObject.java:115)
at org.codehaus.groovy.vmplugin.v8.IndyGuardsFiltersAndSignatures.invokeGroovyObjectInvoker(IndyGuardsFiltersAndSignatures.java:151)
at org.codehaus.groovy.vmplugin.v8.IndyInterface.fromCache(IndyInterface.java:344)
at io.restassured.internal.RequestSpecificationImpl.applyPathParamsAndSendRequest(RequestSpecificationImpl.groovy:1770)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:338)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:274)So, to bypass this problem, I did the following changes in the method:
RequestSpecification local = RestAssured.given(specification);
if (requestParameters.getQueryParams() != null) {
prepareRequestQueryParams(requestParameters, local);
}
if (requestParameters.getBody() != null) {
prepareRequestBody(requestParameters, local);
}
if (requestParameters.getPathParams() != null && !requestParameters.getPathParams().isEmpty()) {
for (Map.Entry<String, String> entry : requestParameters.getPathParams().entrySet()) {
System.out.println("key: " + entry.getKey() + "value: " + entry.getValue());
local.pathParam(entry.getKey(), entry.getValue());
}
}
//TO DO: Remover quando a API estiver deployada no Gateway
RestAssured.useRelaxedHTTPSValidation();
local.log().all();
Response response = switch (requestParameters.getMethod()) {
case Method.GET ->
requestParameters.getEndpoint() != null ? local.when().get(requestParameters.getEndpoint()) : local.when().get();
case Method.POST ->
requestParameters.getEndpoint() != null ? local.when().post(requestParameters.getEndpoint()) : local.when().post();
case Method.PUT ->
requestParameters.getEndpoint() != null ? local.when().put(requestParameters.getEndpoint()) : local.when().put();
case Method.PATCH ->
requestParameters.getEndpoint() != null ? local.when().patch(requestParameters.getEndpoint()) : local.when().patch();
case Method.DELETE ->
requestParameters.getEndpoint() != null ? local.when().delete(requestParameters.getEndpoint()) : local.when().delete();
default -> throw new IllegalArgumentException("Unsupported HTTP method: " + requestParameters.getMethod());
};
response.then().log().all();
return response;
}The problem now is that my headers are duplicated! I have two copies for each header that I added previously.
Can you guys help me solve this problem?! What can I do to avoid RestAssured of duplicating my request headers?!
Source: rest-assured/rest-assured