繁体   English   中英

使用 PATCH 和 Jersey Client API 进行单元测试

[英]Using PATCH with Jersey Client API for unit testing

我正在使用 Jersey 进行 REST API 实现。 对于PATCH (部分更新),我已经实现了我自己的PATCH自定义实现,因为 Jersey 不支持它。

现在我想弄清楚如何围绕该实现编写功能测试。 我正在将 jersey 测试框架用于其他方法( PUTPOSTGETDELETE ),这些方法在该框架中具有可用的支持。

有没有一种方法可以扩展 jersey 测试框架实现来编写我的PATCH功能测试? 如果没有,是否还有其他测试框架可用于测试我的 Jersey PATCH实现?

如果有人可以提供任何示例,那就太好了。

假设您的实现包含这样的自定义注释

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.ws.rs.HttpMethod;

@HttpMethod("PATCH")
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PATCH {}

试图与Client做这样的事情

 String response = target.request().method("PATCH", Entity.text("Hello"), String.class);

默认情况下不支持,并且会出现类似的异常

java.net.ProtocolException: Invalid HTTP method: PATCH

这不是直接使用Client API 的问题,而是使用较低级别的 Java API 的问题。 似乎是一些安全限制。

使用客户端 API,我们可以通过设置属性来覆盖它

JerseyTest ,配置Client一种方法是覆盖configureClient ,并使用ClientConfig设置属性。 您可以轻松地在Client本身上设置属性,但要保持JerseyTest框架的精神(我们不需要显式访问Client ,下面的示例将只是覆盖该方法

public class PatchTest extends JerseyTest {

    @Path("patch")
    public static class PatchResource {
        @PATCH
        @Produces(MediaType.TEXT_PLAIN)
        public String getPatch(String request) {
            return "Patched " + request;
        }
    }

    @Override
    protected void configureClient(final ClientConfig config) {
        config.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true);
    }

    @Override
    public Application configure() {
        return new ResourceConfig(PatchResource.class);
    }

    @Test
    public void doPatchTest() {
        WebTarget target = target("patch");
        String response = target.request().method("PATCH", Entity.text("Hello"), String.class);
        Assert.assertEquals("Patched Hello", response);
        System.out.println(response);
    }
}

要通过JAX RS Client API发送HTTP PATCH而无需任何额外配置:

 client.target("$baseUrl$restUsersUrl/$userId")
                .request("application/json")
                .build("PATCH", Entity.entity(json2Update, MediaType.APPLICATION_JSON))
                .invoke()

注释@PATCH现在在 JAX-RS 2.1 中可用。 您可以在服务器端实现此 HTTP 方法,例如:

@PATCH
public Response updateResource() { ... } 

至于客户端,您可以执行以下操作:

Response r = ClientBuilder.newClient()
    .target("http://localhost:8080/patch")
    .request()
    .build("PATCH", Entity.text("patch"))
    .property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true)
    .invoke();

其中SET_METHOD_WORKAROUND用于避免协议异常,如@peeskillet 所示:

java.net.ProtocolException: Invalid HTTP method: PATCH

使用简单的字符串,这对我有用。 但是当 Patch 方法不接受并返回一个简单的 String 时,有人知道如何做到这一点吗? 请参阅下面的示例。 Response 中的返回类型与传递的参数类型不同。 两者都不是简单的类型。 我总是得到 400 和/或无法构造 ObjectPatch 实例的消息,而不是 200。 我明白这一点,因为它是一个只有一个 apply 方法的接口。 但不知何故在运行时它设法从它构造一个 AttentionPatchResource 对象无论如何。 不幸的是,在使用 JerseyTest 框架时不是。

@PATCH
 @Path("/something")
 @Produces(MediaType.APPLICATION_JSON)
 @Consumes({ PatchMediaTypes.APPLICATION_MERGE_PATCH_JSON, PatchMediaTypes.APPLICATION_JSON_PATCH })
    public Response updateAttention( //
            @Parameter(schema = @Schema(implementation = AttentionPatchResource.class)) ObjectPatch patch) {

        Attention attention = attentionService.find();
        AttentionPatchResource patchResource = attentionAdapter.toPatchResource(attention);

        AttentionPatchResource patchedResource = patch.apply(patchResource);
        Attention patchedAttention = attentionAdapter.fromPatchResource(attention, patchedResource);

        AttentionResource resource = attentionAdapter.toResource(patchedAttention);

        return Response.status(Status.OK).entity(resource).build();
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM