Spring WebFlux如何单元测试Mono.map()中抛出的NoUsersFoundException
问题根本原因
Reactor 中的 Mono/Flux 属于惰性求值的发布者,只有发生订阅行为时,才会执行内部的操作链逻辑。你之前仅调用 doGetUserAccount() 只是拿到了 Mono 实例,没有触发订阅,所以 map 里的空校验逻辑完全不会执行,自然不会抛出异常。
正确测试实现方案
步骤1:正确Mock DAO层返回值
注意要保证Mockito的参数匹配规则和业务代码实际调用时的入参一致,避免Mock不生效:
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; // 配置Mock返回空列表的Mono when(userDao.getUserProfiles(eq(测试用filters), eq(测试用attributes))) .thenReturn(Mono.just(Collections.emptyList()));
如果不需要校验入参,也可以直接用anySet()等参数匹配器代替eq()。
步骤2:用StepVerifier执行验证
通过StepVerifier主动订阅Mono,触发操作链执行并校验异常:
import reactor.test.StepVerifier; // 调用业务方法获取Mono实例 Mono<UserAccount> resultMono = getUserAccount.doGetUserAccount(); // 触发订阅并验证异常 StepVerifier.create(resultMono) // 预期抛出NoUsersFoundException .expectError(NoUsersFoundException.class) // 启动执行并等待流结束 .verify();
可选优化:响应式风格的空校验实现
你当前在map中直接抛出异常的写法可以替换为更符合响应式规范的写法,避免同步抛异常的语义问题:
public Mono<UserAccount> doGetUserAccount() { return userDao.getUserProfiles(filters, attributes) // 过滤非空列表,空列表则进入switchIfEmpty分支 .filter(list -> !CollectionUtils.isEmpty(list)) .switchIfEmpty(Mono.error(new NoUsersFoundException())) .map(this::removePermissions) .map(this::removeDuplicates); }
内容的提问来源于stack exchange,提问作者MeanwhileInHell
相关产品推荐
相关产品推荐

