【问题标题】:Combining database calls using RxJava使用 RxJava 组合数据库调用
【发布时间】:2016-12-02 16:15:02
【问题描述】:

在我的应用程序中,我使用 Repository 和 RxJava 访问我的业务对象。从我的 Presenter 层,我可以要求 Repository 获取我的 ObjectA 或获取我的 ObjectB,Respository 将分别返回一个 Observable 或 Observable。

有时我需要同时获取 ObjectA 和 ObjectB。我想知道使用 RxJava 获取这两个对象的选项是什么,它还允许对我的 Presenter 层进行单元测试。

我最初实现它的方式是使用 flatMap() 运算符。所以我会做这样的事情:

//In Presenter layer
Observable<ObjectA> obsA = repository.getObjectA();
Observable<ObjectB> obsB = repository.getObjectB();

Observable<ObjectB> obsResult = obsA.flatMap(new Func1<ObjectA, Observable<ObjectB>>() {
@Override
public Observable<ObjectB> call(ObjectA a) {
    mObjectA = a;
    return obsB;
}
});

当我订阅 obsResult 时,obsA 运行,我可以在 flatMap() 运算符中访问它的结果。我得到了它的结果的句柄,并将它作为一个字段存储在我的 Presenter 中。然后 obsB 运行,我在我的订阅者中得到它的结果。这工作得很好,但我不禁认为我做得不对。一个问题是,虽然我的 Repository 类中可能有 100% 的测试覆盖率,但现在我正在处理来自 Repository 类的可观察对象,我很难弄清楚如何测试 obsResult 或验证我在 flatMap() 中写的代码是正确的。

我是否应该向我的存储库层添加方法,例如 getObjectAandObjectB 并返回一个 Observable 并在存储库层中完成所有工作?这将允许我在 Repository 层测试中测试生成的 Observable,而不是尝试从两个单独的 Observable 创建一个新的 Observable 并弄清楚如何在我的 Presenter 层中对其进行测试。

我看到的另一件事是使用 zip() 运算符。这看起来像这样:

Observable<ObjectA> obsA = repository.getObjectA();
Observable<ObjectB> obsB = repository.getObjectB();

Observable<CombinedObjectAandObjectB> resultObs = obsA.zipWith(obsB, new Func2<ObjectA, ObjectB, CombinedObjectAandObjectB>() {
            @Override
            public Object call(ObjectA a, ObjectB b) {
                return new CombinedObjectAandObjectB(a,b);
            }
        });

现在,当我订阅我的 resultObs 时,我得到了一个包含 ObjectA 和 Object B 的复合对象。这非常巧妙,但仍然需要我在 Func2 中编写需要测试的代码。

有哪些方法可以实现我的目标,即组合对业务对象的调用,同时还允许结果 Observable 的可测试性?

【问题讨论】:

    标签: android unit-testing rx-java


    【解决方案1】:

    您几乎自己回答了您的问题。根据Clean Architecture,最好将现成的模型传递给表示层。组合逻辑属于领域层。所以在你的存储库中使用zip()(尽管它是数据层)。例如:

    Observable.zip(modelAObservable, modelBOsbervable, (A, B) -> {
                combineModels(A, B);
            })...
    
    private CombinedModel combineModels(modelA, modelB) {
        //combining logic
    }
    

    并像往常一样测试它。例如:

    ModelA A = new ModelA...
    ModelB B = new ModelB...
    CombinedModel expectedResult = new CombinedModel...
    
    assertEquals(combineModels(A, B), expectedResult);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      • 1970-01-01
      • 1970-01-01
      • 2015-10-01
      • 1970-01-01
      相关资源
      最近更新 更多