Android测试 - Robolectric + Mockito + Retrofit获取通知但未调用错误

时间:2016-06-23 10:56:48

标签: java android mockito retrofit robolectric

尝试使用Robolectric和Mockito在我的Android应用中测试我的Retrofit调用,但是我收到以下错误:

  

通缉但未调用:mockApi.register(       ,        );    - >在ServiceTest.testAPI(ServiceTest.java:58)实际上,这个模拟没有交互。

RetroFit API调用在接口中定义如下:

@FormUrlEncoded
@POST("/register")
void register(
        @FieldMap Map<String, String> registrationParams,
        Callback<JsonObject> response) ;

我的测试课如下:

@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服务来自我自己的Application类,我在我的测试文件夹中模拟了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);
    }
}

我已经搜索过有关此错误的其他问题,但这些问题都不符合我在这里要做的事情或提供我的问题的解决方案所以我只是想知道我做错了什么?

1 个答案:

答案 0 :(得分:2)

SharedServiceTestMyApplication的模拟实例与您声明的测试类不同。 Mockito.verify(mockApi).register(Mockito.anyMap(), cb.capture());失败,因为mockApi字段引用的实例实际上从未被调用过。 另一个问题是TestMyApplication中的getter总是为每个invokation返回一个新的模拟:

    @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;
    }
}

并在您的测试类中:

@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());

    ...

}