无法使用JSON实体测试Jax-rs

use*_*937 1 java junit jax-rs jersey resteasy

我正在尝试通过遵循此https://jersey.java.net/documentation/latest/test-framework.html来测试Jax-rs资源,
并且我正在使用容器jersey-test-framework-provider-jdk-http

我可以声明状态码。但是,当我尝试读取实体时,出现异常:

javax.ws.rs.ProcessingException: Unable to find a MessageBodyReader of content-type application/json and type class java.lang.String
    at org.jboss.resteasy.core.interception.ClientReaderInterceptorContext.throwReaderNotFound(ClientReaderInterceptorContext.java:39)
    at org.jboss.resteasy.core.interception.AbstractReaderInterceptorContext.getReader(AbstractReaderInterceptorContext.java:73)
    at org.jboss.resteasy.core.interception.AbstractReaderInterceptorContext.proceed(AbstractReaderInterceptorContext.java:50)
    at org.jboss.resteasy.client.jaxrs.internal.ClientResponse.readFrom(ClientResponse.java:248)
    at org.jboss.resteasy.client.jaxrs.internal.ClientResponse.readEntity(ClientResponse.java:181)
    at org.jboss.resteasy.specimpl.BuiltResponse.readEntity(BuiltResponse.java:217)
Run Code Online (Sandbox Code Playgroud)

我的资源分类:

@Path("/")
public class SampleResource {
    @GET
    @Path("/health")
    @Produces(MediaType.APPLICATION_JSON)
    public String getServiceStatus() {
        return "{\"Status\": \"OK\"}";
    }    
}
Run Code Online (Sandbox Code Playgroud)

我的测试班:

public class TestSampleResource extends JerseyTest {
    @Override
    protected Application configure() {
        return new ResourceConfig(SampleResource.class);
    }

    @Test
    public void testHealthEndpoint() {            
        Response healthResponse = target("health").request(MediaType.APPLICATION_JSON).get();

        Assert.assertEquals(200, healthResponse.getstatus());  // works

        String body = healthResponse.readEntity(String.class);
        Assert.assertEquals("{\"Status\": \"OK\"}", body);
    }        
}
Run Code Online (Sandbox Code Playgroud)

谁能帮忙吗?

Pau*_*tha 6

问题来自在类路径上同时包含Jersey和RestEasy客户端。当您呼叫target()JerseyTestWebTarget会从Client呼叫建立的取得ClientBuilder.newClient()

ClientBuilder是一个标准的JAX-RS API,它是第一个以搜索为实现ClientBuilder通过META-INF/services文件,寻找一个文件名为javax.ws.rs.client.ClientBuilder,其内容是对一个实现的名称ClientBuilder。如果找不到此类文件,则默认为寻找JerseyClientBuilder

jersey-client没有这样的文件,META-INF/services/javax.ws.rs.core.ClientBuilder因为它ClientBuilder是JAX-RS客户端的默认文件。如果您在resteasy-client罐子里看,您会看到它确实具有该文件。而且,如果您查看该文件的内容,您将看到ResteasyClientBuilder实现。

因此,即使您使用的是Jersey的测试框架,ClientRESTeasy的实现也是被使用。而且我猜想实体提供者的所有标准配置都不会被配置。String和application / json之间的转换是您需要的标准提供程序之一。

我想说的就是明确使用Jersey客户端实现。您将不再能够调用targetJerseyTest。您将需要显式创建客户端

@Test
public void dotest() {
    final Client client = new JerseyClientBuilder().build();
    WebTarget target = client.target("http://localhost:9998");
    final Response response = target.path("health").request().get();
    final String json = response.readEntity(String.class);
}
Run Code Online (Sandbox Code Playgroud)

的默认基本路径JerseyTesthttp://localhost:9998,因此我明确地创建了WebTarget

请注意,我说标准提供者支持Stringto / from application/json。因此,如果您仅要序列化字符串,则不需要任何其他操作。如果要对Jersey客户端(和服务器端)进行POJO序列化支持,则应添加以下内容

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>${jersey2.version}</version>
    <scope>test</scope>
</dependency>
Run Code Online (Sandbox Code Playgroud)