我使用Jersey并决定使用GSON而不是Moxy来进行JSON处理(这与Moxy需要使用setter的事实不同)。
到目前为止,一切正常,除了我的JerseyTest
子类中一个非常烦人的问题:自定义GsonProvider
不会被识别,除非为每个调用明确注册。但是,如果我将应用程序部署到Tomcat,就可以识别它。
我的ResourceConfig
:
@ApplicationPath("")
public class MyResourceConfig extends ResourceConfig {
public MyResourceConfig() {
register(GsonProvider.class);
register(SomeResource.class);
}
}
GsonProvider
的实现(尽管我认为它与我遇到的问题无关):@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class GsonProvider<T> implements MessageBodyReader<T>, MessageBodyWriter<T> {
private final Gson mGson;
public GsonProvider() {
mGson = new GsonBuilder().create();
}
@Override
public boolean isReadable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return true;
}
@Override
public T readFrom(Class<T> type, Type genericType, Annotation[] annotations,
MediaType mediaType, MultivaluedMap<String, String> httpHeaders,
InputStream entityStream) throws IOException, WebApplicationException {
InputStreamReader reader = new InputStreamReader(entityStream, "UTF-8");
try {
return mGson.fromJson(reader, type);
} finally {
reader.close();
}
}
@Override
public boolean isWriteable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return true;
}
@Override
public long getSize(T t, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return -1;
}
@Override
public void writeTo(T t, Class<?> type, Type genericType, Annotation[] annotations,
MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream) throws IOException, WebApplicationException {
PrintWriter printWriter = new PrintWriter(entityStream);
try {
String json = mGson.toJson(t);
printWriter.write(json);
printWriter.flush();
} finally {
printWriter.close();
}
}
}
此测试结果为
MessageBodyProviderNotFoundException
:public class SomeResourceTest extends JerseyTest {
@Override
public Application configure() {
return new MyResourceConfig();
}
@Test
public void someApi_200Returned() throws Exception {
// Arrange
// Act
SomeResponse response =
target("/somepath")
.request()
.post(Entity.json(""), SomeResponse.class);
// Assert
assertThat(response.getStatus(), is(200));
}
}
为了解决此问题,我注册了
GsonProvider
请求。以下更改使测试通过:public class SomeResourceTest extends JerseyTest {
@Override
public Application configure() {
return new MyResourceConfig();
}
@Test
public void someApi_200Returned() throws Exception {
// Arrange
// Act
SomeResponse response =
target("/somepath")
.register(GsonProvider.class)
.request()
.post(Entity.json(""), SomeResponse.class);
// Assert
assertThat(response.getStatus(), is(200));
}
}
因此,在
GsonProvider
中注册MyResourceConfig
很适合部署,但是JerseyTest
每个请求都需要额外注册。尽管我可以忍受,但是这很烦人,耗时,并且很难与其他团队成员进行交流。这个问题有解决方案吗?
最佳答案
您没有显示stacktrace,但是我很确定,如果您仔细查看它,它将表明它实际上是客户端错误。您需要做的是也向客户端注册gson提供者,因为您正尝试将响应JSON反序列化为POJO
@Override
public void configureClient(ClientConfig config) {
config.register(GsonProvider.class)
}
configureClient
方法是您可以覆盖的JerseyTest
中的方法。