在 RxJava 中进行单元测试,核心目标是控制线程、控制时间、验证数据流(onNext / onError / onComplete)。下面从「基础做法 → 常用工具 → 示例代码 → 常见坑」逐步说明。
RxJava 单元测试通常关注三点:
Schedulers.trampoline() 或 TestSchedulerTestScheduler 手动推进时间TestObserver / TestSubscribertestImplementation "io.reactivex.rxjava3:rxjava:3.x.x"
testImplementation "junit:junit:4.13.2"
下面示例以 RxJava 3 为例(RxJava 2 几乎一致)
Schedulers.trampoline()适合不涉及延迟 / 定时任务的逻辑
@Before
public void setup() {
RxJavaPlugins.setIoSchedulerHandler(scheduler -> Schedulers.trampoline());
RxJavaPlugins.setComputationSchedulerHandler(scheduler -> Schedulers.trampoline());
}
@Test
public void testMap() {
Observable.just(1, 2, 3)
.map(i -> i * 2)
.test()
.assertResult(2, 4, 6);
}
test() 返回 TestObserver,可以直接断言
@Test
public void testObservable() {
TestObserver<Integer> test = Observable
.just(1, 2, 3)
.test();
test.assertNoErrors();
test.assertValues(1, 2, 3);
test.assertComplete();
}
.assertValues(1, 2, 3)
.assertValueCount(3)
.assertComplete()
.assertError(NullPointerException.class)
.assertNotComplete()
.assertSubscribed()
TestSchedulerTestScheduler scheduler = new TestScheduler();
@Test
public void testDelay() {
TestScheduler scheduler = new TestScheduler();
TestObserver<Long> test = Observable
.interval(1, TimeUnit.SECONDS, scheduler)
.take(3)
.test();
test.assertValueCount(0);
scheduler.advanceTimeBy(1, TimeUnit.SECONDS);
test.assertValues(0L);
scheduler.advanceTimeTo(3, TimeUnit.SECONDS);
test.assertValues(0L, 1L, 2L);
test.assertComplete();
}
✅ 不真实等待时间,测试非常快
@Test
public void testSubject() {
PublishSubject<Integer> subject = PublishSubject.create();
TestObserver<Integer> test = subject.test();
subject.onNext(1);
subject.onNext(2);
subject.onComplete();
test.assertValues(1, 2);
test.assertComplete();
}
@Test
public void testError() {
Observable.error(new RuntimeException("boom"))
.test()
.assertError(RuntimeException.class)
.assertErrorMessage("boom");
}
RxAndroidPlugins@Before
public void setup() {
RxAndroidPlugins.setMainThreadSchedulerHandler(
scheduler -> Schedulers.trampoline()
);
}
public class UserRepository {
Observable<User> getUser() {
return api.getUser()
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.computation());
}
}
@Test
public void testGetUser() {
TestScheduler scheduler = new TestScheduler();
UserRepository repo = new UserRepository();
TestObserver<User> test = repo.getUser()
.subscribeOn(scheduler)
.test();
scheduler.triggerActions();
test.assertValue(user -> user.name != null);
}
❌ 忘记切线程 → 测试卡住
❌ 使用 Thread.sleep()
❌ 忘记 assertComplete()
❌ 在 @Test 中直接 subscribe() 不断言
✅ 正确方式:
TestObserver + TestScheduler + Plugins
| 场景 | 推荐方式 |
|---|---|
| 普通流 | test() |
| 无时间 | Schedulers.trampoline() |
| 有时间 | TestScheduler |
| 异常 | assertError() |
| 主线程 | RxAndroidPlugins |
如果你愿意,我也可以:
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。