JUnit测试异常类型校验问题:RxJava链式调用测试失败求助
解决RxJava单元测试捕获自定义异常失败的问题
首先,你的测试用例失败主要有两个核心原因:
1. 未正确Mock依赖的行为
你直接调用了mService.updateData,但没有预先配置mApiProvider.updateData()的Mock逻辑——它根本不会抛出你预期的RecordNotFoundException,自然触发不了测试的异常断言。
2. RxJava的blockingGet()会包装原始异常
就算mApiProvider真的抛出了异常,RxJava的blockingGet()方法在处理错误信号时,会把原始异常包装进一个RuntimeException(比如OnErrorNotImplementedException)里抛出,而非直接抛出你的自定义异常。所以@Test(expected = RecordNotFound.class)根本匹配不到实际抛出的异常类型。
正确的测试方案(推荐用RxJava官方测试工具)
使用TestObserver订阅Single是RxJava测试的标准做法,它能直接验证错误信号的类型:
@Test public void updateData_recordNotFound() { // 第一步:Mock mApiProvider,让它调用时抛出目标异常 when(mApiProvider.updateData(any(Object.class))).thenThrow(new RecordNotFoundException()); // 第二步:调用方法并获取TestObserver TestObserver<Object> testObserver = mService.updateData(new Object()).test(); // 第三步:验证错误类型是否符合预期 testObserver.assertError(RecordNotFoundException.class); }
若坚持使用blockingGet()的替代方案
如果一定要用blockingGet(),可以捕获包装后的RuntimeException,再检查它的根源是否是你的自定义异常:
@Test public void updateData_recordNotFound() { // 先配置Mock依赖的行为 when(mApiProvider.updateData(any(Object.class))).thenThrow(new RecordNotFoundException()); try { mService.updateData(new Object()).blockingGet(); // 如果走到这里,说明未抛出异常,测试失败 fail("Expected RecordNotFoundException to be thrown"); } catch (RuntimeException e) { // 检查异常的根源是否为目标自定义异常 assertTrue("Exception cause should be RecordNotFoundException", e.getCause() instanceof RecordNotFoundException); } }
额外小优化:简化RxJava业务代码
你原来的Single.defer加手动try-catch可以用Single.fromCallable替代,它会自动捕获Callable中的异常并转为Single的error信号,代码更简洁:
public Single<Object> updateData(Object object){ return Single.fromCallable(() -> mApiProvider.updateData(object)); }
内容的提问来源于stack exchange,提问作者elnino
相关产品推荐
相关产品推荐

