如果发生HttpException,则Retrofit和RxJava的单元测试永远不会完成

时间:2016-02-28 13:34:42

标签: android junit retrofit rx-java

我正在尝试实施单元测试(JUnit),以便在Web服务器返回Retrofit时测试Observable 422 Unprocessable entity

我有以下API服务(我使用retrofit.create(AccountService.class)创建):

public interface AccountService {
   @POST("users")
   Observable<User> createNewUser(@Body User user, @Query("v_uuid") String vUuid, @Query("v_code") String vCode);
}

我从单元测试中调用此服务:

Observable<User> observable = accountService
        .createNewUser(newUser, "uuid", "code")
        .subscribeOn(Schedulers.io());

我也使用TestSubscriber<User>来断言我的Observable:

TestSubscriber<User> testSubscriber = new TestSubscriber<>(); 

observable
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(testSubscriber);

testSubscriber.awaitTerminalEvent();
// assert testSubscriber.getOnErrorEvents()

我使用SchedulersHook(通过JUnit @Rule),如以下博文中所述:http://alexismas.com/blog/2015/05/20/unit-testing-rxjava/。我使用Schedulers.immediate()代替以下调度程序:

  • Schedulers.io()
  • Schedulers.computation()
  • Schedulers.newThread()
  • AndroidSchedulers.mainThread()

但似乎测试永远不会完成。当我拨打observable.observeOn(AndroidSchedulers.mainThread()).subscribe(testSubscriber);时,它会挂起。 同时,如果Web服务器以2xx codes响应,则此代码可以正常工作。此外,如果我从代码中删除自定义SchedulersHook,即使服务器使用4xx codes进行响应,它也会正常工作。

其他信息:我使用MockWebServer来模拟Web服务器,我从日志中看到Retrofit将请求发送到服务器。 我的Gradle依赖关系如下所示:

testCompile 'junit:junit:4.12'
testCompile 'org.robolectric:robolectric:3.1-SNAPSHOT'
testCompile 'com.squareup.okhttp3:mockwebserver:3.1.2'

compile 'io.reactivex:rxjava:1.1.0'
compile 'io.reactivex:rxandroid:1.1.0'
compile 'com.squareup.okhttp3:okhttp:3.1.2'
compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0-beta4'

更新 在深入研究rxjava后,我发现使用merge运算符和不同的Schedulers(特别是使用SchedulersHook替换它们)会导致sleeps()内的OperatorMerge.InnerSubscriber<T>无限class HashAuthBackend(ModelBackend): def authenticate(self, hash=None): try: user = User.objects.get(profile__login_hash=hash) if user.is_active: return user except: return None 1}}。

1 个答案:

答案 0 :(得分:1)

我终于找到了原因代码永远不会完成的原因。感谢来自社区的DávidKarnok(https://groups.google.com/forum/#!topic/rxjava/2rOHj1mvShk):

  

RxRingBuffer的清理线程会在立即调度程序上休眠,从而阻止其他组件的进展。

     

立即调度程序存在根本问题;它不是一个真正的调度程序,由于它的睡眠性质,它可能会导致意外的挂起。

     

对于测试运算符,最好直接使用TestScheduler并尽可能避免使用RxJavaPlugins。

在我切换到TestScheduler后,一切都按预期开始工作。

还建议使用依赖注入(Dagger 2)来管理Schedulers