簡體   English   中英

如何聲明Completable是否已訂閱/完成(RxJava2)

[英]How to assert if a Completable has been subscribed/completed (RxJava2)

我無法確定我的測試中是否已訂閱Completable ,例如:

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情況下重寫sync方法,如下所示:

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

然后我的測試會通過,但代碼不起作用,因為即使我認為我已經調用了insert方法,我也沒有在其中調用subscribe()

我該怎么辦呢?

PS我是RxJava的新手,所以如果我沒有使用最好的做法,我很想知道:)

更新

修正了Maxim Ostrovidov指出的不調用.ingnoreElements()的錯誤

您可以使用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使用Observable發出的項目訂閱傳遞的Completable

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

編輯

要測試repository.insert訂閱的事實,您可以使用另一個TestObserverCompletable與應用的doOnSubscribe

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();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM