是否可以同步 运行 一个 Retrofit observable?

Is it possible to run a Retrofit observable synchronously?

我正在尝试迁移我的应用程序以使用 RxJava。 我已经在使用 Retrofit,因此我正在尝试使用方法 return Observables 的 Retrofit 接口。 但是,我现在在针对它进行编码测试时遇到问题,因为我无法在主线程上将 Observable 设置为 运行;我正在尝试为此使用 Scheduler.immediate() 。 似乎 Retrofit 不允许覆盖它的行为,这对实际执行流程来说完全有意义,但它使测试变得非常困难。 因为我刚刚开始使用 RxJava + Retrofit,所以我希望我做错了什么。

代码如下所示:

@Test
public void shouldCompleteRequest() {
    SomeRestRequest request = new SomeRestRequest(arg1, arg2);
    TestSubscriber<SomeRestResponse> testSubscriber = new TestSubscriber<>();
    new SomeRestCommand(mRestApi,
            arg1, arg2
            Schedulers.immediate(),
            Schedulers.immediate(),
            mMockEventBus).execute(request, testSubscriber);
    testSubscriber.assertCompleted();
}

其中

public void execute(T request, Observer<S> observer) {
    getCommand(request)
        .observeOn(mObserveOnScheduler) //The test injects Schedulers.immediate()
        .subscribeOn(mSubscribeOnScheduler) //The test injects Schedulers.immediate()
        .subscribe(observer);
}

,

@Override
protected Observable<SomeRestResponse> getCommand(SomeRestRequest request) {
    return mRestApi.restCommand(arg1, arg2);
}

public interface RestApi {
    @GET("/someEndPoint")
    Observable<SomeRestResponse> restCommand(@Query("arg1") String arg1, @Query("arg2") String arg2);
}

如果您修改测试以添加 testSubscriber.awaitTerminalEvent();,那么您的测试将等待调用完成,因此测试将通过。您仍然需要执行 assertCompleted(),因为终端事件可以是成功完成也可以是错误。

@Test
public void shouldCompleteRequest() {
    SomeRestRequest request = new SomeRestRequest(arg1, arg2);
    TestSubscriber<SomeRestResponse> testSubscriber = new TestSubscriber<>();
    new SomeRestCommand(mRestApi,
            arg1, arg2
            Schedulers.immediate(),
            Schedulers.immediate(),
            mMockEventBus).execute(request, testSubscriber);

    testSubscriber.awaitTerminalEvent(); // add this line here
    testSubscriber.assertCompleted();
}

我查阅了 Retrofit 1.9.0 的源代码,根据 RxSupport class,调用总是在 httpExecutor 提供的单独线程中执行。因此使用 Schedulers.immediate() 不会导致调用发生在主线程中。