2017-06-27 48 views
1

我使用Jersey并决定使用GSON而不是Moxy进行JSON处理(不喜欢Moxy需要setter的事实)。MessageBodyProviderNotFoundException在使用GSON时在JerseyTest中抛出

一切工作正常,直到现在,除了在我的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)); 
    } 
} 

为了解决这个问题我reg请求的是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)); 
    } 
} 

所以,在MyResourceConfigGsonProvider注册好部署,但JerseyTest要求每个请求的附加注册。

虽然我能忍受,但它很烦人,耗时且很难与其他团队成员沟通。这个问题的任何解决方案?

回答

1

你还没有显示堆栈跟踪,但我敢肯定,如果仔细观察它,它会显示它实际上是一个客户端错误。你需要做的是注册与客户端的GSON提供商也因为你试图反序列化JSON响应的POJO

@Override 
public void configureClient(ClientConfig config) { 
    config.register(GsonProvider.class) 
} 

configureClient方法在JerseyTest,你可以覆盖的方法。

+0

是的!我没有意识到客户是一个独立的实体。谢谢 – Vasiliy

+0

我必须在任何通话中注册提供商,它确实有效。但是,我确信有一个通用的方法来解决这个问题,你的答案正是我所需要的。把这个逻辑放到'MyJerseyTest'基类中,生活又好了:) – Vasiliy

相关问题