早些时候,我的项目使用的是Retrofit,当我编写单元测试时,一切似乎都很好。现在我们使用compile 'com.squareup.retrofit2:retrofit:2.0.0'
升级到Retrofit 2.0
。我们正在使用 Robolectric 进行单元测试。这是我们为早期改造版本编写的测试。
@Test
public void testButton() throws Exception {
button.setText("www.google.com");
button.performClick();
Mockito.verify(mockApiservice).getLinkDetails(requestArgumentCaptor.capture());
assertThat(requestArgumentCaptor.getValue()).isEqualTo("www.google.com");
assertThat(button.getVisibility()).isEqualTo(View.GONE);
}
现在当我们升级到Retrofit 2.0
,button
点击实际代码更改为
Call<MyPOJO> callObj = ApiService.getLinkDetails(encodedUrlString);
callObj.enqueue(this);
即使我将测试代码更改为 - 测试也失败了 -
@Test
public void testButton() throws Exception {
button.setText("www.google.com");
button.performClick();
assertThat(button.getVisibility()).isEqualTo(View.GONE);
}
我现在得到的错误是 -
java.lang.NullPointerException at callObj.enqueue(this);
这意味着callObj
为空所以两个最重要的问题——
为什么我在实际代码中获取 NPE?
如何更改测试代码以向 API 发出模拟请求并获得模拟响应?
我到处寻找,但没有任何线索。请帮助我。任何意见都非常感谢。
日志猫 -
java.lang.NullPointerException
at com.myapp.MyFragment.onButtonClick(MyFragment.java:428)
at com.myapp.fragment.MyFragment.access$100(MyFragment.java:62)
at com.myapp.fragment.MyFragment$3.onClick(MyFragment.java:148)
at android.view.View.performClick(View.java:4756)
at com.myapp.MyFragmentTest.testButton(MyFragmentTest.java:122)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:251)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:188)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:152)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
我可能已经想通了 - 看起来您正在将getLinkDetails
调用为静态方法,但您需要这样做:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://url.com/")
.build();
ApiService service = retrofit.create(ApiService.class);
Call<MyPOJO> callObj = service.getLinkDetails(encodedUrlString);
callObj.enqueue(this);
您可以重用Retrofit
对象和服务对象,但不能重用Call
。
改造 2 文档:http://square.github.io/retrofit/