Jersey 测试 - 使用 JSON 请求的 Http Delete 方法

Jersey test - Http Delete method with JSON request

我正在使用 Jersey Test 来测试 Rest 服务 DELETE 方法:

@DELETE
@Path("/myPath")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public MyResponse myMethod(MyRequest myRequest) {

我试过下面的例子和其他方法:

Entity<MyRequest> requestEntity = Entity.entity(new MyRequest(arg1, arg2), MediaType.APPLICATION_JSON);

target(MY_URI).request(MediaType.APPLICATION_JSON).method("DELETE", requestEntity)

target(MY_URI).request(MediaType.APPLICATION_JSON).build("DELETE", requestEntity).invoke();

但是不行。

如何在Jersey测试中进行Http删除?

根据 HTTP 规范

If a DELETE request includes an entity body, the body is ignored

虽然很多服务器仍然支持实体主体,但我猜是因为这个 Jersey 认为主体违反了 HTTP 合规性。泽西岛验证是否符合客户要求。要绕过此验证,您可以设置客户端 属性

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.

要在JerseyTest中配置它,你可以

@Override
public void configureClient(ClientConfig config) {
   config.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
}

假设您通过调用 JerseyTesttarget(..) 方法发出请求,以上配置将适用于所有请求。如果只是想去除某些请求的验证,也可以在WebTarget上设置属性,不做上面的配置。

target(...).property(...).request()...

编辑

我可能要提到的另一件事是,Grizzly 是不支持实体 的服务器之一。我不太确定如何在 JerseyTest 中配置它。因此,如果您使用的是 Grizzly 测试提供程序,它甚至可能无法在服务器端工作。

如果是这种情况,您尝试使用内存测试提供程序,或者使用jetty提供程序

编辑灰熊配置

编辑由Emanuele Lombardi

提供

您可以使用以下代码段配置 Grizzly 测试提供程序:

@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;
        }
    };
}

应在 GrizzlyServer 启动之前调用以下方法。

server.getServerConfiguration().setAllowPayloadForUndefinedHttpMethods(true)‌​;

使用反射检索服务器实例(在此示例中通过 org.apache.commons.lang3.reflect.FieldUtils#readDeclaredField)。
此代码在 server 字段名称未更改为 GrizzlyTestContainerFactory#GrizzlyTestContainer 之前有效,但对我来说似乎是一种合理的方法,至少在单元测试中是这样。