【问题标题】:Unit testing RxJava composition and functionality单元测试 RxJava 的组成和功能
【发布时间】:2017-03-10 22:32:53
【问题描述】:

在我的架构中,我使用了一个名为 UseCase 的类来组成一个 observable 并订阅它。 UseCase 在构造函数中接收一个或多个 Repositories,并有一个“execute”方法负责创建 observable 并订阅它。

这是一个简单的例子;

public class MyUseCase {
    IRepoA mRepoA;
    IRepoB mRepoB;
    Scheduler mScheduleOn;
    Scheduler mObserveOn;
    CompositeSubscription mCompositeSubscription;

    public MyUseCase(IRepoA repoA, IRepoB repoB, Scheduler subscribeOn, Scheduler observeOn, CompositeSubscription compositeSubscription) {
    mRepoA = repoA;
    mRepoB = repoB;
    mSubscribeOn = subscribeOn;
    mObserveOn = observeOn;
    mCompositeSubscription = compositeSubscription;
}

public Observable execute(Observable observable, Subscriber subscriber) {
    if (observable == null) {
                     observable = mRepoA
                    .fetchLoginPreference()
                    .map(new Func1<LoginPreference, String>() {
                        @Override
                        public String call(LoginPreference loginPreference) {
                            return loginPreference.getActivationCode();
                        }
                    })
                    .flatMap(new Func1<String, Observable<List<RegistrationField>>>() {
                        @Override
                        public Observable<List<RegistrationField>> call(String s) {
                            return mRepoB.fetchRegistrationFields(s);
                        }
                    })
    }
    mCompositeSubscription.add(observable.subscribeOn(mSubscribeOn).observeOn(mObserveOn).subscribe(observable));
    return observable;
}
}

在我看来,这里有几件事要测试,我想知道最好的方法是什么。

1) 我想测试 observables 的组合是否正确。也就是说,我想确保调用了 .map()、.flatMap() 和 .cache()。我之前这样做的方法是使用模拟并验证这些方法是否在模拟上被调用。例如,repoA.fetchLoginPreference() 将返回一个模拟 observable,然后我可以验证该模拟是否调用了 .map() 等等。

2) 我想测试当我订阅 observable 时它的行为是否正确。为了测试这一点,我所做的是使用真正的 Observables 而不是模拟。所以当 repoA.fetchLoginPreference() 被调用时,我会让它返回 Observable.just(mockLoginPreference)。然后我使用 TestSubscriber 订阅生成的 observable 并验证从 Func1 回调中正确调用了模拟。

这看起来是一种理智的做事方式吗?我最终能够测试组合是否正确,并验证当订阅 observable 时它实际上做了它应该做的,但我很好奇是否有更好的方法。

【问题讨论】:

    标签: unit-testing rx-java


    【解决方案1】:

    当您学习 RxJava 的行为时,您的第一种方法可能很有用,尤其是对于更奇特的运算符,例如 switchMap()。但是,您不需要特别测试 rxjava 库本身的正确性。

    第二种方法很有意义。拥有一个结合了模拟和可观察/测试订阅者的单元测试工具是反应式编程的一个非常强大的特性。

    话虽如此,在处理CompositeSubscription() 时,您可能需要这两种方法,因为我认为它不会像您认为的那样做。需要一些低级调试探针来确保在线程上完成操作

    【讨论】:

    • 我认为第一种方法除了测试 rxjava 库本身的正确性之外很有用。假设您要求 .cache() 运算符存在于您的组合中,您将如何测试它?如果其他开发人员删除了 .cache() 运算符怎么办?有没有办法确保在不测试组合的情况下调用它? (如果有,很高兴知道)。
    • 您在复合订阅中看到了什么让您说“我认为它没有按照您的想法执行”?从技术上讲,只创建了一个订阅,因此复合订阅永远不会有多个订阅,这就是您这么说的原因吗?
    • 我的部分困惑是您在订阅行中颠倒了subscriberobservable 的角色。
    • 你不想测试实现——你想测试功能。一方面,我面前的代码没有使用cache(),所以我不确定你指的是什么。 cache() 运算符的功能可以用 ReplaySubject 代替,而您应该永远不知道其中的区别。
    • 好的,所以你是说虽然你可以测试组合是否正确,但更好的整体测试是验证行为是否正确(这是我不知道如何验证的事情使用缓存运算符时)
    猜你喜欢
    • 2020-09-25
    • 2021-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-05
    相关资源
    最近更新 更多