RESTEasy InMemoryClient使用@FormParam抛出NPE

时间:2014-01-17 08:45:40

标签: java unit-testing jax-rs resteasy

我正在使用RESTEasy客户端框架版本2.3.5(我不得不使用它,但我可以稍后升级到更新版本)来创建对数据库服务器的请求。 我google了很多,以便更好地了解我应该如何为它编写好的和干净的单元测试。 我找到了似乎符合我需要的InMemoryClientExecutor类。

请参阅此答案:Is there a client-side mock framework for RESTEasy?

它工作得很好,但是如果我在客户端代码中添加一个方法(我在生产代码中使用相同的签名方法)

@POST
@Produces({ "application/json" })
public abstract HighLevelDeviceGateway testMethod(@FormParam("deviceGatewayName")   String param)
            throws Exception;

抛出NPE,这是堆栈跟踪:

Exception in thread "main" java.lang.RuntimeException: java.lang.NullPointerException
at org.jboss.resteasy.client.core.ClientInvoker.invoke(ClientInvoker.java:120)
at org.jboss.resteasy.client.core.ClientProxy.invoke(ClientProxy.java:88)
at com.sun.proxy.$Proxy24.testMethod(Unknown Source)
at com.mypackage.InMemoryClientExecutorExample.main(InMemoryClientExecutorExample.java:78)
Caused by: java.lang.NullPointerException
at org.jboss.resteasy.mock.MockHttpRequest.getFormParameters(MockHttpRequest.java:259)
at org.jboss.resteasy.client.core.executors.InMemoryClientExecutor.loadHttpMethod(InMemoryClientExecutor.java:147)
at org.jboss.resteasy.client.core.executors.InMemoryClientExecutor.execute(InMemoryClientExecutor.java:75)
at org.jboss.resteasy.core.interception.ClientExecutionContextImpl.proceed(ClientExecutionContextImpl.java:39)
at org.jboss.resteasy.plugins.interceptors.encoding.AcceptEncodingGZIPInterceptor.execute(AcceptEncodingGZIPInterceptor.java:40)
at org.jboss.resteasy.core.interception.ClientExecutionContextImpl.proceed(ClientExecutionContextImpl.java:45)
at org.jboss.resteasy.client.ClientRequest.execute(ClientRequest.java:443)
at org.jboss.resteasy.client.ClientRequest.httpMethod(ClientRequest.java:677)
at org.jboss.resteasy.client.core.ClientInvoker.invoke(ClientInvoker.java:111)
... 3 more

对我而言,这似乎是一个错误,我尝试使用最新版本的RESTEasy,NPE仍然存在但新版本却弃用了Executor。

更多信息,这是NPE的来源:

if (getHttpHeaders().getMediaType().isCompatible(MediaType.valueOf("application/x-www-form-urlencoded")))

HTTP标头不是null但媒体类型是,我不明白为什么..

感谢任何帮助!

1 个答案:

答案 0 :(得分:2)

您可以通过添加" Content-Type"来绕过第一个NPE。标题为您的请求:

_request.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED);

但是,这不会解决您的问题。

根本问题是InMemoryClientExecutor错误地调用了

mockHttpRequest.getFormParameters().add(key, value);

添加from值而不是调用

mockHttpRequest.addFormHeader(key, value);

因为formParameters集合以null开头,所以调用getFormParameters()会导致尝试解析输入流为空。

看起来addFormHeader用于将内容类型(" application / x-www-form-urlencoded")和表单名称/值对设置为已解码的表单参数集合

可悲的是,由于代码的整个ClientExecutionContextImplClientRequest分支似乎被标记为已弃用,我怀疑其中任何一个都将被修复。我希望我们得到一些进程方式来测试对资源的调度。 :S

现在,您只需使用表单参数构建MultivalueMap集合并将其设置为请求正文:

_request.body(MediaType.APPLICATION_FORM_URLENCODED_TYPE, _formData);

这将允许您发送"表格数据:)