RxJava的操作序列

时间:2018-07-30 11:58:35

标签: rx-java rx-java2

我想执行一系列操作。下一个只有在前一个成功的情况下才能执行。为了提高我的理解,我决定尝试使用RxJava来实现它。

操作顺序如下:

  1. 登录
  2. 存储登录结果
  3. 使用登录结果检索用户信息
  4. 存储用户信息

为此,我使用以下内容:

public interface LoginRepository {

    Single<LoginResponseEntity> login(@NonNull final Credentials credentials);

    Completable storeLoginResult(@NonNull final LoginResponseEntity loginEntity);
}

public interface UserSettingsRepository {

    Single<UserInfoEntity> retrieveUserInfo(@NonNull final String email, final String accessToken);

    Completable storeUserInfo(@NonNull final UserInfoEntity userInfoEntity);
}

和登录用例:

public Completable execute(@NonNull final Credentials credentials) {
    return loginRepository.login(credentials)
            .flatMap(loginEntity -> loginRepository.storeLoginResult(loginEntity)
                    .andThen(userSettingsRepository.retrieveUserInfo(credentials.getEmail(),
                            loginEntity.getAccessToken()))
            ).flatMapCompletable(userSettingsRepository::storeUserInfo)
            .andThen(saveIsAlreadyLogged.execute());
}

因此,为了测试这一点,我创建了单元测试(在Kotlin中)。除以下两项外,全部通过:

@Test
fun `when storing login result failed, don't retrieve user info`() {
    val exception = Exception()
    whenever(loginRepository.login(any())).thenReturn(Single.just(loginResponseEntity()))
    whenever(loginRepository.storeLoginResult(any())).thenReturn(Completable.error(exception))
    whenever(saveIsAlreadyLogged.execute()).thenReturn(Completable.complete())

    val test = login.execute(credentials()).test()

    verify(userSettingsRepository, never()).retrieveUserInfo(anyString(), anyString())
}

错误:

org.mockito.exceptions.verification.NeverWantedButInvoked: 
userSettingsRepository.retrieveUserInfo(
    <any string>,
    <any string>
);

@Test
fun `when storing login result failed, login should error`() {
    val exception = Exception()
    whenever(loginRepository.login(any())).thenReturn(Single.just(loginResponseEntity()))
    whenever(loginRepository.storeLoginResult(any())).thenReturn(Completable.error(exception))
    whenever(saveIsAlreadyLogged.execute()).thenReturn(Completable.complete())

    val test = login.execute(credentials()).test()

    test.assertError(exception)
}

错误:

java.lang.AssertionError: Error not present (latch = 0, values = 0, errors = 1, completions = 0)

您知道我在做什么错吗? 您是否有改进我的代码的技巧?请在我仍在学习的同时给出明确的解释。

1 个答案:

答案 0 :(得分:1)

对于第一种情况,问题出在:

.andThen(
    userSettingsRepository.retrieveUserInfo(
        credentials.getEmail(),
        loginEntity.getAccessToken()
    )
)

请注意,retrieveUserInfo的调用已完成,无论您之前遇到的情况如何。换句话说:这是在设置流时执行的,而不是在运行时执行的。您可能想在then内使用Observable.defer来满足您的期望。

对于第二个问题,您可以看到正在发生错误:

java.lang.AssertionError: Error not present (latch = 0, values = 0, errors = 1, completions = 0)

errors = 1表示这一点,您需要查看完整的消息以查看错误是什么(如@akarnokd所指出的那样)