2016-12-02 47 views
1

在我的应用程序中,我使用Repository和RxJava访问业务对象。从我的Presenter层,我可以让存储库获取ObjectA或者让我ObjectB,Respository将分别返回一个Observable或Observable。使用RxJava结合数据库调用

有时我需要同时获得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,表外业务运行,我可以在flatMap()运算符访问其结果。我得到它的结果句柄并将它作为字段存储在我的Presenter中。然后obsB运行,并在我的订户中得到它的结果。这工作得很好,但我不禁觉得我没有做得对。一个问题是,虽然我的Repository类中可能有100%的测试覆盖率,但现在我正在操作来自Repository类的observables,而且我很难弄清楚如何测试obsResult或验证我在flatMap()中写的代码是正确的。

我应该向我的Repository层添加方法,比如getObjectAandObjectB并返回一个Observable并完成Repository层的所有工作?这将允许我在Repository层测试中测试合成的Observable,而不是试图从两个独立的Observables创建一个新的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我得到的复合物与两个对象A和对象B这是非常漂亮的返回,但仍然需要我FUNC2编写的代码,需要进行测试。

有什么方法可以实现我的业务对象调用的目标,同时考虑到Observable的可测试性?

回答

0

你几乎可以自己问你的问题。根据Clean Architecture,最好将随时可用的模型传递给表示层。组合逻辑属于域层。因此在您的Repository中使用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);