Mockito测试RxJava含FlatMap的代码时无法进入FlatMap内部如何解决
问题原因
- Mockito注解未生效。如果测试类没有添加Mockito的运行器/扩展注解(Junit4加
@RunWith(MockitoJUnitRunner.class),Junit5加@ExtendWith(MockitoExtension.class)),@Mock标注的objectResolver不会被实例化,默认是null。当流执行到flatMap内部调用objectResolver.resolve时直接抛出空指针异常,流直接进入onError终止,自然不会执行后续逻辑,且当前测试代码没有捕获错误,只会收到测试失败结果,看不到具体异常。 - 参数匹配与Stub不匹配。你测试中传入
toTest方法的是new Object(),如果代码中的Object是Java自带的java.lang.Object而非自定义业务类,它根本没有getField()、getAnotherField()方法,调用时会直接抛出异常;就算是自定义类,若getField()返回的参数和Stub时的any()匹配规则冲突(比如方法参数是基本类型但any()匹配的是包装类型),也会导致Stub不生效,resolve方法返回null或者默认值,触发空指针。 - 测试代码语法错误。你提供的测试代码中
when(objectResolver.resolve(any()).thenReturn(Mono.just(new ResolvedObject()))缺少右括号,正确写法是when(objectResolver.resolve(any())).thenReturn(Mono.just(new ResolvedObject())),语法错误会导致Stub设置失败。 - 若你Stub返回的
new ResolvedObject()的getField()返回值、传入toTest的业务对象的getAnotherField()返回值拼接后和期望的"resultString"不一致,也会导致测试失败,但这种情况是进入了flatMap逻辑只是结果不对,不符合无法进入内部的现象。
解决步骤
- 给测试类添加Mockito启动注解
Junit4示例:
Junit5示例:@RunWith(MockitoJUnitRunner.class) public class CodeTest { // 测试代码 }@ExtendWith(MockitoExtension.class) public class CodeTest { // 测试代码 } - 修正测试代码的语法错误,同时明确参数匹配规则,确认参数匹配没问题可以用
any(),否则用具体的参数值匹配:when(objectResolver.resolve(any())).thenReturn(Mono.just(new ResolvedObject())); - 使用自定义的业务对象作为入参,不要和
java.lang.Object重名避免歧义,同时给测试用到的字段设置明确的返回值,避免空指针:
示例:// 假设自定义业务类叫BizObject,不要叫Object避免冲突 BizObject testObj = new BizObject(); testObj.setField("testField"); testObj.setAnotherField("anotherField"); ResolvedObject resolvedObject = new ResolvedObject(); resolvedObject.setField("resolvedField"); when(objectResolver.resolve(eq("testField"))).thenReturn(Mono.just(resolvedObject)); - 调整测试代码,先开启错误日志或者添加
expectError排查异常,确认问题后再校验结果:
排查阶段可以这么写查看具体报错:
确认无异常后再改成你需要的校验逻辑:StepVerifier.create(code.toTest(testObj)) .consumeErrorWith(Throwable::printStackTrace) .verify();StepVerifier.create(code.toTest(testObj)) .expectNext("resolvedFieldanotherField") // 和实际拼接的结果保持一致 .verifyComplete();
内容的提问来源于stack exchange,提问作者Shubhankar Agrawal
相关产品推荐
相关产品推荐

