Android testing - Robolectric + Mockito + Retrofit getting Wanted but not invoked 错误
Android testing - Robolectric + Mockito + Retrofit getting Wanted but not invoked error
尝试使用 Robolectric 和 Mockito 在我的 Android 应用程序中测试我的 Retrofit 调用,但我收到以下错误:
Wanted but not invoked: mockApi.register(
,
);
-> at ServiceTest.testAPI(ServiceTest.java:58) Actually, there were zero interactions with this mock.
RetroFit API调用在接口中定义如下:
@FormUrlEncoded
@POST("/register")
void register(
@FieldMap Map<String, String> registrationParams,
Callback<JsonObject> response) ;
我的测试class如下:
@Config(constants = BuildConfig.class)
@RunWith(TestRunner.class)
public class SharedServiceTest {
private RegistrationActivity activity;
@Mock
private SharedService mockApi;
@Captor
private ArgumentCaptor<Callback<JsonObject>> cb;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
ActivityController<RegistrationActivity> controller = Robolectric.buildActivity(RegistrationActivity.class);
activity = controller.get();
controller.create();
}
@Test
public void testAPI() throws Exception {
activity.populateFields();
activity.validateFields();
activity.register("");
Mockito.verify(mockApi).register(Mockito.anyMap(), cb.capture());
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("sessionToken", Mockito.anyString());
jsonObject.addProperty("userId", Mockito.anyString());
cb.getValue().success(jsonObject, null);
Assert.assertTrue(ShadowToast.getTextOfLatestToast().contains("Registration completed"));
}
}
我的RegistrationActivity中使用API的方法如下:
public void register(){
MyApplication.getInstance().getSharedService().register(mRegistrationParams, new Callback<JsonObject>() {
@Override
public void success(JsonObject jsonObject, retrofit.client.Response response) {
Toast.makeText(RegistrationActivity.this, "Registration completed", Toast.LENGTH_LONG).show();
}
@Override
public void failure(RetrofitError error) {
Toast.makeText(RegistrationActivity.this, RetrofitUtils.getErrorMessage(error), Toast.LENGTH_LONG).show();
}
});
}
真正的 Retrofit 服务来自我自己的应用程序 class,我在我的测试文件夹中模拟了它以供 robolectric 使用:
public class TestMyApplication extends MyApplication
implements TestLifecycleApplication {
@Override
public void onCreate() {
super.onCreate();
}
@Override public void beforeTest(Method method) {
}
@Override public void prepareTest(Object test) {
}
@Override public void afterTest(Method method) {
}
@Override public CPSharedService getCPSharedService() {
return Mockito.mock(SharedService.class);
}
}
我搜索了 SO 上出现此错误的其他问题,但其中 none 匹配我在这里尝试做的事情或为我的问题提供解决方案,所以我只是想知道我在做什么错了?
您 TestMyApplication
中 SharedService
的模拟实例与您声明的测试 class 不同。
Mockito.verify(mockApi).register(Mockito.anyMap(), cb.capture());
失败是因为 mockApi
字段引用的实例实际上从未被调用过。
另一个问题是 TestMyApplication
中的 getter 总是 returns 每个调用的新模拟:
@Override public CPSharedService getCPSharedService() {
return Mockito.mock(SharedService.class); //this creates a new "mocked" instance
}
我不是 100% 清楚你的场景,但如果你能让你的测试在你的 TestMyApplication 实例中设置 mockApi 字段的实例会更好:
public class TestMyApplication extends MyApplication
implements TestLifecycleApplication {
private SharedService sharedService;
@Override
public void onCreate() {
super.onCreate();
}
@Override public void beforeTest(Method method) {
}
@Override public void prepareTest(Object test) {
}
@Override public void afterTest(Method method) {
}
@Override public CPSharedService getCPSharedService() {
return this.sharedService;
}
public void setCPSharedService(SharedService sharedService) {
// store your mock
this.sharedService = sharedService;
}
}
在你的测试中 class:
@Test
public void testAPI() throws Exception {
// configure you TestMyApplication
assertTrue(MyApplication.getInstance() instanceof TestMyApplication);
TestMyApplication testMyApp = (TestMyApplication) MyApplication.getInstance();
testMyApp.setCPSharedService(this.mockApi);
activity.populateFields();
activity.validateFields();
activity.register("");
Mockito.verify(this.mockApi).register(Mockito.anyMap(), cb.capture());
...
}
尝试使用 Robolectric 和 Mockito 在我的 Android 应用程序中测试我的 Retrofit 调用,但我收到以下错误:
Wanted but not invoked: mockApi.register( , ); -> at ServiceTest.testAPI(ServiceTest.java:58) Actually, there were zero interactions with this mock.
RetroFit API调用在接口中定义如下:
@FormUrlEncoded
@POST("/register")
void register(
@FieldMap Map<String, String> registrationParams,
Callback<JsonObject> response) ;
我的测试class如下:
@Config(constants = BuildConfig.class)
@RunWith(TestRunner.class)
public class SharedServiceTest {
private RegistrationActivity activity;
@Mock
private SharedService mockApi;
@Captor
private ArgumentCaptor<Callback<JsonObject>> cb;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
ActivityController<RegistrationActivity> controller = Robolectric.buildActivity(RegistrationActivity.class);
activity = controller.get();
controller.create();
}
@Test
public void testAPI() throws Exception {
activity.populateFields();
activity.validateFields();
activity.register("");
Mockito.verify(mockApi).register(Mockito.anyMap(), cb.capture());
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("sessionToken", Mockito.anyString());
jsonObject.addProperty("userId", Mockito.anyString());
cb.getValue().success(jsonObject, null);
Assert.assertTrue(ShadowToast.getTextOfLatestToast().contains("Registration completed"));
}
}
我的RegistrationActivity中使用API的方法如下:
public void register(){
MyApplication.getInstance().getSharedService().register(mRegistrationParams, new Callback<JsonObject>() {
@Override
public void success(JsonObject jsonObject, retrofit.client.Response response) {
Toast.makeText(RegistrationActivity.this, "Registration completed", Toast.LENGTH_LONG).show();
}
@Override
public void failure(RetrofitError error) {
Toast.makeText(RegistrationActivity.this, RetrofitUtils.getErrorMessage(error), Toast.LENGTH_LONG).show();
}
});
}
真正的 Retrofit 服务来自我自己的应用程序 class,我在我的测试文件夹中模拟了它以供 robolectric 使用:
public class TestMyApplication extends MyApplication
implements TestLifecycleApplication {
@Override
public void onCreate() {
super.onCreate();
}
@Override public void beforeTest(Method method) {
}
@Override public void prepareTest(Object test) {
}
@Override public void afterTest(Method method) {
}
@Override public CPSharedService getCPSharedService() {
return Mockito.mock(SharedService.class);
}
}
我搜索了 SO 上出现此错误的其他问题,但其中 none 匹配我在这里尝试做的事情或为我的问题提供解决方案,所以我只是想知道我在做什么错了?
您 TestMyApplication
中 SharedService
的模拟实例与您声明的测试 class 不同。
Mockito.verify(mockApi).register(Mockito.anyMap(), cb.capture());
失败是因为 mockApi
字段引用的实例实际上从未被调用过。
另一个问题是 TestMyApplication
中的 getter 总是 returns 每个调用的新模拟:
@Override public CPSharedService getCPSharedService() {
return Mockito.mock(SharedService.class); //this creates a new "mocked" instance
}
我不是 100% 清楚你的场景,但如果你能让你的测试在你的 TestMyApplication 实例中设置 mockApi 字段的实例会更好:
public class TestMyApplication extends MyApplication
implements TestLifecycleApplication {
private SharedService sharedService;
@Override
public void onCreate() {
super.onCreate();
}
@Override public void beforeTest(Method method) {
}
@Override public void prepareTest(Object test) {
}
@Override public void afterTest(Method method) {
}
@Override public CPSharedService getCPSharedService() {
return this.sharedService;
}
public void setCPSharedService(SharedService sharedService) {
// store your mock
this.sharedService = sharedService;
}
}
在你的测试中 class:
@Test
public void testAPI() throws Exception {
// configure you TestMyApplication
assertTrue(MyApplication.getInstance() instanceof TestMyApplication);
TestMyApplication testMyApp = (TestMyApplication) MyApplication.getInstance();
testMyApp.setCPSharedService(this.mockApi);
activity.populateFields();
activity.validateFields();
activity.register("");
Mockito.verify(this.mockApi).register(Mockito.anyMap(), cb.capture());
...
}