简体   繁体   English

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

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

I'm having trouble identifying if a Completable has been subscribed to in my tests, for example: 我无法确定我的测试中是否已订阅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) })
    }
}

And then in my tests: 然后在我的测试中:

@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);
}

This test will pass. 这个测试将通过。 But I Could rewrite the sync method without using flatMapCompletable like this: 但是我可以在不使用flatMapCompletable情况下重写sync方法,如下所示:

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

Then my tests would pass but code would not work because even thought I've called the insert method, I've not called subscribe() in it. 然后我的测试会通过,但代码不起作用,因为即使我认为我已经调用了insert方法,我也没有在其中调用subscribe()

How should I proceed about this? 我该怎么办呢?

PS I am new to RxJava so if I am not using the best practices I would love to know :) PS我是RxJava的新手,所以如果我没有使用最好的做法,我很想知道:)

Update 更新

Fixed the mistake of not calling .ingnoreElements() pointed by Maxim Ostrovidov 修正了Maxim Ostrovidov指出的不调用.ingnoreElements()的错误

You can use test() operator for convinience: 您可以使用test()运算符:

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

But I Could rewrite the sync method without using flatMapCompletable like this: 但是我可以在不使用flatMapCompletable的情况下重写sync方法,如下所示:

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

This won't compile because doOnNext is used only to invoke actions on items, not changing the stream return type. 这不会编译,因为doOnNext仅用于调用对项的操作,而不是更改流返回类型。 In your case method is expecting Completable but actually it will be Observable<Data> . 在你的情况下,方法期望Completable但实际上它将是Observable<Data>

Even if you force change the eventual stream type: 即使您强制更改最终的流类型:

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

repository.insert(data) will not be invoked because doOnNext is not subscribing to anything you passed and not returning anything: repository.insert(data)将不会被调用,因为doOnNext没有订阅你传递的任何内容并且没有返回任何内容:

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

    }
})

Your initial code is the best for what you want to achieve: 您的初始代码最适合您想要实现的目标:

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

flatMapCompletable subscribes to passed Completable using items emitted by Observable : flatMapCompletable使用Observable发出的项目订阅传递的Completable

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

Edit 编辑

To test the fact of repository.insert subscription you can use another TestObserver and Completable with applied doOnSubscribe : 要测试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