android - (RxJava2)Single.blockingGet() 不适用于单元测试
问题描述
我为返回 Rx Single 的交互器方法创建单元测试。Single 必须异步返回一个用户的 bean。我尝试为 Single 调用 blockingGet() 但 bean 没有返回,因为测试无休止地工作。我检查了断点,发现 bean 已创建但没有返回。我还尝试为 Single 调用 test().values().get(0) 但它不包含 bean。断点没有调用。
我可以理解这是什么问题。我需要帮助来解决它。
交互器中的方法。
public Single<UserBean> verifyUser() {
String jwt = getJWTToken();
if (TextUtils.isEmpty(jwt)) {
return Single.error(new EmptyJWTException());
}
if (!checkConnectionInfo()) {
return Single.error(new NotNetworkConnectedException());
}
return Single.create((SingleOnSubscribe<UserBean>) emitter -> {
UserBean resultBean = mAuthenticationRepository.verifyUserByJwt(jwt);
if (resultBean != null && !TextUtils.isEmpty(resultBean.getId())) {
emitter.onSuccess(resultBean);
} else {
emitter.onError(new RequestToServerException());
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
单元测试。
@RunWith(MockitoJUnitRunner.class)
public class AuthenticationInteractorTest {
@Mock
private Application mApplication;
@Mock
private IAuthenticationRepository mAuthenticationRepository;
@Mock
private SharedPreferences mSharedPreferences;
@Mock
private ConnectivityManager mConnectivityManager;
@Mock
private NetworkInfo mNetworkInfo;
private AuthenticationInteractor mInteractor;
@Before
public void setUp() {
mInteractor = new AuthenticationInteractor(mAuthenticationRepository, mApplication);
}
@Test
public void verifyUserTest() {
String jwt = "jwt";
UserBean userBean = createUserBean();
when(mApplication.getSharedPreferences(AuthenticationInteractor.SHARED_PREFS, Context.MODE_PRIVATE)).thenReturn(mSharedPreferences);
when(mSharedPreferences.getString(AuthenticationInteractor.TOKEN_KEY, null)).thenReturn(jwt);
when((ConnectivityManager) mApplication.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(mConnectivityManager);
when(mConnectivityManager.getActiveNetworkInfo()).thenReturn(mNetworkInfo);
when(mNetworkInfo.isConnected()).thenReturn(true);
when(mAuthenticationRepository.verifyUserByJwt(jwt)).thenReturn(userBean);
UserBean bean = mInteractor.verifyUser().blockingGet();
assertEquals(userBean, bean);
}
private UserBean createUserBean() {
UserBean userBean = new UserBean();
userBean.setMetaId("1539762652616:940c29e6d716:15:jmt4z02l:11182");
userBean.setJWT("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Im1hZ2F6b240aWtAeWFuZGV4LnJ1IiwiY3MiOiI1OWEwNDA2MTgzNDAwMDAwIiwiaWF0IjoxNTM5NzYyNjUyLCJhdWQiOiIqLmxvY2FsaG9zdCIsImlzcyI6Im1zLXVzZXJzIn0.2AcuLZjR_-GyWAFen7JczJ5-W37zQWGbnRRErGLqDEY");
userBean.setId("test@test.test");
userBean.setType("user");
userBean.setUserName("test@test.test");
userBean.setCreated(1535970916310L);
userBean.setLatestResult("1539676474685");
userBean.setOnDiet("No");
return userBean;
}
}
解决方案
看起来您没有覆盖正在使用的调度程序。如果不这样做,您几乎肯定会在尝试使用订阅时收到以下错误AndroidSchedulers.mainThread
android.os.Looper 中的方法 getMainLooper 未模拟
为了克服这个问题,您可以创建一个 TestRule ,它允许您为测试指定调度程序,例如以下将重置Schedulers.io
和AndroidSchedulers.mainThread
使用Schedulers.trampoline
.
public class RxSchedulersRule implements TestRule {
@Override
public Statement apply(final Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
RxAndroidPlugins.reset();
RxJavaPlugins.reset();
RxAndroidPlugins.setInitMainThreadSchedulerHandler(s -> Schedulers.trampoline());
RxJavaPlugins.setIoSchedulerHandler(s -> Schedulers.trampoline());
try {
base.evaluate();
} finally {
RxAndroidPlugins.reset();
RxJavaPlugins.reset();
}
}
};
}
}
要在您的测试中使用,您需要声明规则
@Rule public final RxSchedulersRule schedulersRule = new RxSchedulersRule();
推荐阅读
- javascript - JavaScript 提示窗口中的按钮不起作用
- c# - 如何使用文本框作为输入在 DataGridView 中搜索特定行?
- json - 用 Swift 解析 JSON 会导致“......它的格式不正确。”
- google-bigquery - 如何将 CSV 中的 MULTIPOLYGON 数据加载到 Bigquery 中?
- typescript - 如何为 AppSync 订阅 Websocket 端点配置 Aws Amplify?
- php - 无法将验证码放置在应该使用 php 的位置
- c - 如何在 mplab 中为 PIC18F4550 制作 RGB LED 作品?
- php - 带代理的 PHP cURL(不是 SOCKS5)
- pandas - 从数据框中删除除 index 和 nth 之外的所有列
- stripe-payments - Stripe connect - 在付款过程中保存卡