我尝试了几种方法来模拟和监视值,并在每次出现nullPointerException或其他Mockito错误时调用下面的方法。由于我是Mockito和android本身的新手,请让我知道如何为下面的方法编写AndroidTest案例,该方法也使用改装API调用。我正在尝试编写涵盖整个方法的代码。提前感谢
public LiveData<BaseModel<Onboarding>> updateUser(Result item) {
final MutableLiveData<BaseModel<Onboarding>> data = new MutableLiveData<>();
final BaseModel<Onboarding> dataWrapper = new BaseModel<>();
Map<String, String> headers = WaApplication.getContext().getRequestHeaders();
String tenantId = WaApplication.getContext().getTenantId();
service.updateUser(tenantId,headers, item).enqueue(new Callback<UserOnboarding>() {
@Override
public void onResponse(Call<Onboarding> call, Response<Onboarding> response) {
dataWrapper.setData(response.body());
dataWrapper.setResponseCode(response.code());
data.setValue(dataWrapper);
LogUtils.d(TAG, "updateUser:HTTPS_ONBOARDING_API_ENDPOINT: "+ BuildConfig.HTTPS_ONBOARDING_API_ENDPOINT);
LogUtils.d("OnBoardingService onRes", new Gson().toJson(response.body()));
}
@Override
public void onFailure(Call<Onboarding> call, Throwable t) {
LogUtils.e(TAG, "OnBoardingService API Failed. Error - " + t.getMessage());
data.setValue(null);
}
});
return data;
}
TL;DR:
@Rule
public InstantTaskExecutorRule InstantTaskExecutorRule = new InstantTaskExecutorRule();
我假设您想要编写一个单元测试(在JVM上运行(,而不是一个Instrumentation测试(在Android设备上运行(
在单元测试中,您对data.setValue((的调用将导致:
java.lang.RuntimeException: Method getMainLooper in android.os.Looper not mocked. See http://g.co/androidstudio/not-mocked for details.
at android.os.Looper.getMainLooper(Looper.java)
为了能够在JVM上的单元测试中使用Android类,android.jar
被添加到类路径中。这个jar包含所有的Android类,但没有实现它们。因此,如果你执行它的任何代码,它总是抛出上面的异常。Android方法调用的真正实现仅在Android设备上可用。
因此,一般来说,对于单元测试,您必须使用例如Mockito来模拟方法调用。
或者,您可以将测试作为Instrumentation测试执行(将其放入androidTest
源代码集中(。然后在安卓设备上执行。
不过,在LiveData
的情况下,您可以通过更改LiveData
的调度方式来避免这种情况。Google为这种情况提供了一个JUnit测试规则,您必须将一个工件添加到build.gradle
,并将TestRule
添加到测试类
build.gradle:
testImplementation 'androidx.arch.core:core-testing:2.1.0'
测试等级:
@Rule
public InstantTaskExecutorRule InstantTaskExecutorRule = new InstantTaskExecutorRule();
附带说明:
- 不要在单元测试中对真实的URL进行网络或
Retrofit
调用。最好将baseUrl
指向模拟服务器,并使用例如OkHttp MockWebServer伪造网络响应 - 如果你的
ViewModel
中没有updateUser
方法,你想把它放在那里。因为这正是ViewModel
的用例 - 如果在
ViewModel
中有updateUser
方法,则不需要返回LiveData
。data
LiveData
应该是ViewModel
的实例变量,然后您可以在Activity
或Fragment
中观察到它 - 你可能想使用android事实上的日志标准Timber,而不是自定义的
LogUtils