【问题标题】:retryWhen() doesn't call what's inside Observable.just()retryWhen() 不会调用 Observable.just() 中的内容
【发布时间】:2017-03-02 10:59:25
【问题描述】:

我有一个测试,我在其中检查令牌授权的重试机制。在该测试中,我在开始时将 null 作为令牌返回,然后返回一个有效令牌,如下所示:

whenever(accountManager.getToken())
            .thenReturn(null)
            .thenReturn("some_token") 

然后我有一个 Observable:

    return Observable.just(accountManager.getToken())
            ...
            .retryWhen { retryOnAuthExceptionWithBackoff(it) }

它应该获取令牌,将其发送到某个地方,等待响应,然后响应错误,重试整个过程,直到成功。

问题是当retryWhen()启动时,源observable没有被再次调用,只是立即返回了它的初始值。

另一方面,这确实工作:

    return Observable.just(null)
            .map{ accountManager.getToken() }
            ...
            .retryWhen { retryOnAuthExceptionWithBackoff(it) }

这是设计使然还是错误?如果是设计使然,那么写这个的优雅方式是什么,因为Observable.just(null) 看起来很丑。

【问题讨论】:

  • 让我重新排列你的代码: Object x = accountManager.getToken(); System.out.println(x); System.out.println(x); //
  • 不,在您的示例中,您只调用了一次getToken()。如果你写了Object x = accountManager.getToken();Object y = accountManager.getToken();,那么在我的例子中y 不会为空。关键是在第二次读取accountManager.getToken() 时,它已经有了令牌。如果该函数在 Observable.just 内被解析两次,它将返回不同的值(就像我在第二个示例中所做的那样)。
  • 你认为 just() 会调用你的 getToken 函数吗?错误的。 Just() 接受一个常量值引用,并不断将 same 引用分发给订阅者。
  • 我就是这么想的。但是感谢您确保我这样做。现在,你知道比映射 null 更优雅的解决方案吗?
  • Observable.fromCallable(() -> accountManager.getToken()).

标签: unit-testing mockito rx-java kotlin observable


【解决方案1】:

just() 采用常量值引用,并不断向订阅者分发相同的引用。

你需要的是fromCallable:

Observable.fromCallable(() -> accountManager.getToken())
...

每当有新订阅者(例如重试)进入时,都会再次执行 lambda。

【讨论】:

  • 感谢您的提示!由于retryWhenrepeatWhen 没有再次调用该函数来获取新的Observable,而是重新订阅了以前的observable,所以直到现在我还不确定如何从重新订阅中返回不同的值。如果您想测试“失败然后成功”的场景,这尤其有用,因为您无法在错误后发出项目。
猜你喜欢
  • 2019-07-05
  • 1970-01-01
  • 2021-06-14
  • 2018-06-08
  • 2020-10-21
  • 1970-01-01
  • 1970-01-01
  • 2013-07-10
  • 1970-01-01
相关资源
最近更新 更多