2016-02-28 44 views
2

我試圖執行單元測試(JUnit),測試RetrofitObservable在萬維網服務器返回422 Unprocessable entity的情況下。如果發生HttpException,Retrofit和RxJava的單元測試永遠不會結束

我有以下的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>我可觀察:

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);時,它會掛起。 與此同時,如果網絡服務器響應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' 

UPDATE: 挖成rxjava後,我發現,使用merge運營商和不同Schedulers(尤其是利用SchedulersHook替換它們)會導致內部OperatorMerge.InnerSubscriber<T>無限sleeps()地方。

+0

目前還不清楚你想測試什麼。 'RxJava'核心方法如何工作('observeOn','subscribe')?我敢打賭他們工作正常。或者你簡化了你的例子,你在測試中有一些'flatMap'或'map'運算符用法? – eleven

+0

@foxinsocks,我是一個初學者,有'rxjava'和'retrofit'。我想研究這些東西是如何工作的。在這一刻我沒有其他操作符,我只想看看'Retrofit'' HttpException'是如何傳播到'Subscriber'(當前是'TestSubscriber')的。但是我認爲他們(其他操作員)會出現在進一步的代碼中。無論如何,額外的操作員會影響這種行爲嗎? – peppered

+0

是的,'運營商'影響流和異常傳播。沒有什麼值得注意的,因爲任何'Observable':所有'errors' /'exceptions'都會進入'subscriber'的'onError'處理程序。在'onError'處理函數內部,你可以將'Throwable'強制轉換爲'RetrofitError'並獲得狀態碼。 – eleven

回答

1

我終於想出了原因代碼從未完成。感謝David Karnok來自社區(https://groups.google.com/forum/#!topic/rxjava/2rOHj1mvShk):

會發生什麼情況是,RxRingBuffer的清理線程睡在即時調度,防止對其他組件的任何進展。

即時調度程序存在一個基本問題;它不是一個真正的調度程序,並且由於它的睡眠性質,它可能會導致意外掛起。

對於測試運算符,直接使用TestScheduler並儘可能避免使用RxJavaPlugins要好得多。

在我切換到TestScheduler之後,一切都開始按預期工作。

還建議使用依賴注入(Dagger 2)來管理Schedulers