【问题标题】:How to verify no interactions on RxJava2 Observable using Mockito如何使用 Mockito 验证 RxJava2 Observable 上没有交互
【发布时间】:2017-05-19 13:49:57
【问题描述】:

Observable 是最终类,因此我们无法为其创建模拟来验证或捕获对其执行的任何交互。

和Observable的test()一样,TestSubscriber也没有提供任何这样的交互断言技术

我创建了一个通用方法,用于在从网络加载之前检查缓存数据

/**
 * General parametrized method for loading data from service while checking connection
 * and respecting reload state
 */
private <T> Observable<T> getData(Observable<T> dataSource, String key, boolean reload) {
    T cachedData = (T) cacheModel.getValue(key);

    // Do not use cache if reloading
    if(!reload && cachedData != null)
        return Observable.just(cachedData);

    if(!utilModel.isConnected()) {
        return Observable.error(new Throwable(Constants.NO_NETWORK));
    }

    return dataSource
        .doOnNext(data -> cacheModel.saveObject(key, data))
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread());
}

并按如下方式使用它:

@Override
public Observable<User> getOrganiser(boolean reload) {
    return getData(eventService.getUser(authorization), ORGANIZER, reload);
}

以前,我什至没有调用 eventService.getUser(...) 来获取 observable,所以我可以测试它是否从未被调用,但现在,由于我必须将它传递给模板方法,我需要调用它但验证如果缓存存在,则永远不会与之交互。

这是我之前的测试,现在明显失败了

@Test
public void shouldLoadOrganizerFromCache() {
    // Clear cache
    objectCache.clear();

    User user = new User();
    objectCache.saveObject(RetrofitEventRepository.ORGANIZER, user);

    // No force reload ensures use of cache
    Observable<User> userObservable = retrofitEventModel.getOrganiser(false);

    userObservable.test().assertNoErrors();
    userObservable.test().assertValue(user);

    verify(eventService, never()).getUser(auth);
}

【问题讨论】:

    标签: android testing mockito rx-java2


    【解决方案1】:

    假设您要测试的 Observable 是这样的:

    Observable<User> userObservable = getData(eventService.getUser(authorization));
    

    虽然您不能直接使用test() 方法或使用TestObserver 订阅,但您将输入Observable 交给不同的实体。您可以使用Observable 副作用方法来验证与Observable 的几乎所有交互。
    例如,在您的情况下,您可以使用 doOnSubscribe 并在它被调用时引发一个标志(表明服务方法被调用,而它不应该被调用,因为应该调用缓存):

    final boolean[] serviceCalled = new boolean[1];
    Observable<User> userServiceObservable = eventService.getUser(authorization)
                .doOnSubscribe(disposable -> serviceCalled[0] = true);
    
    Observable<User> userObservable = getData(userServiceObservable, ORGANIZER, reload);
    userObservable.test()
            .assertNoErrors()
            .assertValue(user)
            .awaitTerminalEvent();
    Assert.assertEquals(false, serviceCalled[0]);
    

    顺便说一句,您的缓存方法可能无法像您在获取Observable 时测试缓存而不是在订阅时那样工作,因此缓存状态在订阅时可能会有所不同。多个调用也可能同时发生,导致对服务器的多个调用和更新缓存,你可以看到here我使用Observable.defer()缓存的建议。

    【讨论】:

    • 随着时间的推移,测试订阅者将进行的交互变得僵化,因为我只是在测试存储库而不是与演示者一起测试存储库,因此返回的 observable 将永远不会真正被订阅,所以我可以' t 测试并感谢您的缓存实现。我正在寻找它,但找不到它。我知道会有一种更被动的方式来做到这一点。
    猜你喜欢
    • 2013-06-16
    • 2011-02-24
    • 2012-08-14
    • 1970-01-01
    • 2015-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多