You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 06:54:04