I am using Jersey Test to test Rest service DELETE method:
@DELETE
@Path("/myPath")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public MyResponse myMethod(MyRequest myRequest) {
I have tried the example below and other methods:
Entity<MyRequest> requestEntity = Entity.entity(new MyRequest(arg1, arg2), MediaType.APPLICATION_JSON);
target(MY_URI).request(MediaType.APPLICATION_JSON).method("DELETE", requestEntity)
and
target(MY_URI).request(MediaType.APPLICATION_JSON).build("DELETE", requestEntity).invoke();
But it does not work.
How to make Http Delete in Jersey test?
According to the HTTP specification
If a DELETE request includes an entity body, the body is ignored
Though a lot servers still support the entity body, I guess because of this Jersey considers the body as breaking HTTP Compliance. Jersey validates compliance with client requests. To get around this validation, you can set the client property
ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION
If true, the strict validation of HTTP specification compliance will be suppressed.
By default, Jersey client runtime performs certain HTTP compliance checks (such as which HTTP methods can facilitate non-empty request entities etc.) in order to fail fast with an exception when user tries to establish a communication non-compliant with HTTP specification. Users who need to override these compliance checks and avoid the exceptions being thrown by Jersey client runtime for some reason, can set this property to true. As a result, the compliance issues will be merely reported in a log and no exceptions will be thrown.
Note that the property suppresses the Jersey layer exceptions. Chances are that the non-compliant behavior will cause different set of exceptions being raised in the underlying I/O connector layer.
This property can be configured in a client runtime configuration or directly on an individual request. In case of conflict, request-specific property value takes precedence over value configured in the runtime configuration.
The default value is false.
To configure it in JerseyTest
, you can do
@Override
public void configureClient(ClientConfig config) {
config.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
}
Assuming you are making your requests by calling the target(..)
method of the JerseyTest
, the above configuration will be for all request. If you just want to remove the validation for certain requests, you can also set the property on the WebTarget
and not do the above configuration.
target(...).property(...).request()...
Another thing I might mention is that Grizzly is one of the servers that doesn't support the entity, unless configured. I'm not quite sure though how to configure that in JerseyTest. So if you are using the Grizzly test provider, it may not even work on the server side.
If this is the case, you try to use the in-memory test provider, or use the jetty provider
Edit provided by Emanuele Lombardi
You can configure the Grizzly test provider by using the following snippet:
@Override
protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
return new TestContainerFactory() {
private final GrizzlyTestContainerFactory grizzlyTestContainerFactory = new GrizzlyTestContainerFactory();
@Override
public TestContainer create(URI baseUri, DeploymentContext deploymentContext) {
TestContainer testContainer = grizzlyTestContainerFactory.create(baseUri, deploymentContext);
try {
HttpServer server = (HttpServer) FieldUtils.readDeclaredField(testContainer, "server", true);
server.getServerConfiguration().setAllowPayloadForUndefinedHttpMethods(true);
} catch (IllegalAccessException e) {
fail(e.getMessage());
}
return testContainer;
}
};
}
The below method should be invoked before the GrizzlyServer starts.
server.getServerConfiguration().setAllowPayloadForUndefinedHttpMethods(true);
The server instance is retrieved using reflection (in this example through org.apache.commons.lang3.reflect.FieldUtils#readDeclaredField
).
This code works until the server
field name is not changed into GrizzlyTestContainerFactory#GrizzlyTestContainer
, but seems a reasonable approach to me, at least in a unit test.