我在我的android项目中使用RxJava,我实际上开始单元测试我的代码。
我有下面的Observable方法我要测试
private Observable<Boolean> changeMyString (@NonNull String testString) {
return OneClass
.doSth1(testString)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.flatMap(testString2 -> Observable.create(
subscriber -> {
manager.setTestString2(testString2);
AnotherClass
.doSth2(testString2)
.subscribe(
testString3 -> {
manager.setTestString3(testString3);
subscriber.onNext(success);
},
subscriber::onError,
subscriber::onCompleted
);
}
));
onecclass .java doSth1(String testString)
private Observable<Object> doSth1 (@NonNull String testString) {
return Observable.create(subscriber -> {
try {
testString = "CHANGEDSTRING"
subscriber.onNext(testString);
subscriber.onCompleted();
}
catch (Exception e) {
subscriber.onError(e);
}
});
}
AnotherClass.java doSth2(Object someObject)
public Observable<String> doSth2 (@NonNull Object someObject) {
return Observable.create(subscriber -> {
String changeText = preferences.getString(ANYSTRING, null); //preferences = SharedPrefences
if (StringHelper.isEmpty(changeText)) {
subscriber.onCompleted();
return;
}
try {
String finishedString = "WE ARE DONE! " + someObject.toString();
subscriber.onNext(finishedString);
subscriber.onCompleted();
}
catch (Exception e) {
subscriber.onError(e);
}
});
}
我的测试用例如下所示:
TestSubscriber<Boolean> testSubscriber = new TestSubscriber<>();
ClassToTest.changeMyString("TESTSTRING").subscribe(testSubscriber);
当我调试我的代码时,它没有到达这里的这一部分:
...
.flatMap(testString2 -> Observable.create(
subscriber -> {
manager.setTestString2(testString2);
AnotherClass
.doSth2(testString2)
.subscribe(
testString3 -> {
manager.setTestString3(testString3);
subscriber.onNext(success);
},
subscriber::onError,
subscriber::onCompleted
);
}
));
我如何为这种情况编写单元测试?我不明白,为什么它不工作……
谢谢你的帮助!
奥尔本
与其直接使用scheduler,不如注入它并使用TestScheduler
。它将允许你控制执行。(对于单元测试,处理其他调度器可能会比较复杂)
有关TestScheduler
的更多信息:如何在RxJava中使用TestScheduler
class YourClass {
private final Scheduler ioScheduler;
private final Scheduler uiScheduler;
public YourClass(Scheduler ioScheduler, Scheduler uiScheduler) {
this.ioScheduler = ioScheduler;
this.uiScheduler = uiScheduler;
}
private Observable<Boolean> changeMyString (@NonNull String testString) {
return OneClass.doSth1(testString)
.subscribeOn(ioScheduler)
.observeOn(uiScheduler)
.doOnNext(str -> manager.setTestString2(str))
.flatMap(testString2 -> AnotherClass
.doSth2(testString2))
.doOnNext(str -> manager.setString3(str));
}
}
那么在你的测试中,你可以注射一个TestScheduler
代替:
@Test
public void example() {
TestScheduler ui = new TestScheduler();
TestScheduler io = new TestScheduler();
YourClass hello = new YourClass(io, ui);
TestSubscriber subscriber = new TestSubscriber();
hello.changeMyString("stuff").subscribe(subscriber);
io.advanceByTime(2, SECONDS);
ui.advanceByTime(2, SECONDS);
// perform check on subscriber here
}
请注意,我重构了你的代码,因为你应该避免嵌套订阅。
在onSubscribe中创建一个新的Observable流通常是一个坏主意。
你应该考虑这样做:
OneClass
.doSth1(testString)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnNext(testString2 -> manager.setTestString2(testString2))
.flatMap(testString2 -> AnotherClass.doSth2(testString2))
.doOnNext(testString3 -> manager.setTestString3(testString3))
.map(setTestString3 -> true);
从我在你的代码中看到的,这应该给你你想要的