我正在尝试实施单元测试(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}}。
答案 0 :(得分:1)
我终于找到了原因代码永远不会完成的原因。感谢来自社区的DávidKarnok(https://groups.google.com/forum/#!topic/rxjava/2rOHj1mvShk):
RxRingBuffer的清理线程会在立即调度程序上休眠,从而阻止其他组件的进展。
立即调度程序存在根本问题;它不是一个真正的调度程序,由于它的睡眠性质,它可能会导致意外的挂起。
对于测试运算符,最好直接使用TestScheduler并尽可能避免使用RxJavaPlugins。
在我切换到TestScheduler
后,一切都按预期开始工作。
还建议使用依赖注入(Dagger 2
)来管理Schedulers
。