如何声明Completable是否已订阅/完成(RxJava2)

时间:2017-01-17 13:57:24

标签: java unit-testing mockito rx-java rx-java2

我无法确定我的测试中是否已订阅interface IWebApi { Observable<Data> download(); } interface IDataRepository { Completable insert(Data data); } class SyncService { IWebApi webApi; IDataRepository repository; public SyncService(IWebApi webApi, IDataRepository repository) { this.webApi = webApi; this.repository = repository; } public Completable sync() { return webApi.download() .flatMapCompletable((Data data) -> { repository.insert(data) }) } } ,例如:

@Test
public void syncTest() {
    Data data = new Data();
    IDataRepository repository = mock (IDataRepository.class);
    IWebApi webApi = mock (IWebApi.class);

    given(webApi.download()).willReturn(Observable.just(data));
    given(repository.insert(data)).willReturn(Completable.complete());

    TestObserver<Void> observer = new TestObserver<Void>();
    SyncService service = new SyncService(webApi, repository);
    service.sync()
            .subscribe(observer);

    observer.assertComplete();
    verify(repository).insert(data);
}

然后在我的测试中:

flatMapCompletable

此测试将通过。但我可以在不使用 public Completable sync() { return webApi.download() .doOnNext((Data data) -> { repository.insert(data) }) .ignoreElements(); } 的情况下重写同步方法:

subscribe()

然后我的测试会通过,但代码无效,因为即使我认为我已经调用了insert方法,我也没有在其中调用.ingnoreElements()

我该如何处理?

P.S我是RxJava的新手,所以如果我没有使用我想知道的最佳实践:)

更新

修正了Maxim Ostrovidov指出的不调用.something { padding: 5px; @include media-breakpoint-up(sm) { padding: 20px; } @include media-breakpoint-up(md) { padding: 40px; } } 的错误

1 个答案:

答案 0 :(得分:4)

您可以使用test()运算符:

SyncService service = new SyncService(webApi, repository);
TestObserver observer = service.sync().test();
  

但我可以在不使用flatMapCompletable的情况下重写sync方法:

public Completable sync() {
    return webApi.download()
        .doOnNext((Data data) -> { repository.insert(data) })
}

这不会编译,因为doOnNext仅用于调用对项的操作,而不是更改流返回类型。在您的情况下,方法需要Completable,但实际上它将是Observable<Data>

即使您强制更改最终的流类型:

public Completable sync() {
    return webApi.download()
        .doOnNext((Data data) -> { repository.insert(data) })
        .ignoreElements(); //converts to Completable
}

repository.insert(data)将不会被调用,因为doOnNext未订阅您传递的任何内容而未返回任何内容:

//under the hood of lambdas
.doOnNext(new Consumer<Data>() {
    @Override
    public void accept(Data data) throws Exception {

    }
})

您的初始代码最适合您想要达到的目标:

public Completable sync() {
    return webApi.download()
        .flatMapCompletable((Data data) -> { repository.insert(data) })
}

flatMapCompletable使用Completable发出的项目订阅传递Observable

.flatMapCompletable(new Function<Data, CompletableSource>() {
    @Override
    public CompletableSource apply(Data data) throws Exception {
        return repository.insert(data);
    }
})

修改

要测试repository.insert订阅的事实,您可以使用已应用TestObserver的其他CompletabledoOnSubscribe

TestObserver repositoryInsertObserver = TestObserver.create();
Completable insertCompletable = Completable.complete()
    .doOnSubscribe(d -> repositoryInsertObserver.onSubscribe(d));

//pass completable to your mock
given(repository.insert(data)).willReturn(insertCompletable);

//and verify that subscription took place
repositoryInsertObserver.assertSubscribed();