使用带有 Jersey Client API 的 PATCH 进行单元测试
Using PATCH with Jersey Client API for unit testing
我正在使用 Jersey 开发 REST API 实现。对于 PATCH
(部分更新),我实现了自己的 PATCH
自定义实现,因为 Jersey 不支持它。
现在我正试图弄清楚如何围绕该实现编写功能测试。我正在为其他方法(PUT
、POST
、GET
、DELETE
)使用球衣测试框架,该框架支持该框架。
有什么方法可以扩展 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()
JAX-RS 2.1 现在可以使用注释 @PATCH
。您可以在服务器端实现此 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 方法不接受并且 return 一个简单的字符串时,有人知道如何做到这一点吗?请参阅下面的示例。
响应中的 return 类型与传递参数的类型不同。两者都不是简单类型。
我总是收到 400 and/or 消息,而不是 200,它无法构造 ObjectPatch 实例。我明白这一点,因为它是一个只有 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();
}
我正在使用 Jersey 开发 REST API 实现。对于 PATCH
(部分更新),我实现了自己的 PATCH
自定义实现,因为 Jersey 不支持它。
现在我正试图弄清楚如何围绕该实现编写功能测试。我正在为其他方法(PUT
、POST
、GET
、DELETE
)使用球衣测试框架,该框架支持该框架。
有什么方法可以扩展 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()
JAX-RS 2.1 现在可以使用注释 @PATCH
。您可以在服务器端实现此 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 方法不接受并且 return 一个简单的字符串时,有人知道如何做到这一点吗?请参阅下面的示例。 响应中的 return 类型与传递参数的类型不同。两者都不是简单类型。 我总是收到 400 and/or 消息,而不是 200,它无法构造 ObjectPatch 实例。我明白这一点,因为它是一个只有 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();
}