【问题标题】:Using PATCH with Jersey Client API for unit testing使用带有 Jersey 客户端 API 的 PATCH 进行单元测试
【发布时间】:2015-06-12 11:50:48
【问题描述】:

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

现在我正试图弄清楚如何围绕该实现编写功能测试。我正在为其他方法(PUTPOSTGETDELETE)使用球衣测试框架,该框架中提供了该支持。

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

如果有人能提供任何例子,那就太好了。

【问题讨论】:

    标签: java rest jax-rs jersey-2.0 http-patch


    【解决方案1】:

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

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

    【讨论】:

    • 我只是这样使用它,它在客户端上没有任何配置。 String response = target.request().method("PATCH", Entity.text("Hello"), String.class);
    • 最新版本的 JAX-RS 现在支持 PATCH。
    【解决方案2】:

    无需任何额外配置即可通过JAX RS Client API 发送HTTP PATCH

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

    【讨论】:

      【解决方案3】:

      注释@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
      

      【讨论】:

        【解决方案4】:

        使用简单的字符串,这对我有用。但是,当 Patch 方法不接受并返回一个简单的字符串时,有谁知道如何做到这一点?请参阅下面的示例。 Response 中的返回类型与传递参数的类型不同。两者都不是简单的类型。 而不是 200,我总是得到 400 和/或它无法构造 ObjectPatch 实例的消息。我明白这一点,因为它是一个只有应用方法的接口。但不知何故,它在运行时设法从中构造了一个 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();
            }
        

        【讨论】:

        • 我不明白。你在问问题吗?
        • 如果您有问题并且不回答旧帖子,请创建一个新问题。
        • 我已经找到了解决方案。下次我将开始一个单独的问题,但我认为本质上是同一个问题,这就是为什么我没有。作为对 Scrattle 的回应。是的,我在问一个问题。我的帖子里只有一个带问号的句子,这可能是问题吗?不过如果你觉得不清楚也没关系。
        猜你喜欢
        • 1970-01-01
        • 2014-04-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-09
        • 2016-03-27
        相关资源
        最近更新 更多