
本文介绍在基于 mutiny 的 quarkus 项目中,如何正确编写单元测试来断言 `uni
在使用 SmallRye Mutiny 进行响应式编程时,Uni 是处理单个异步结果的核心类型。当业务逻辑需在数据缺失时主动抛出异常(如 BusinessException),测试该异常是否被正确触发就变得至关重要。但直接复用 Multi 的 AssertSubscriber 会导致编译错误——因为 Uni 和 Multi 的订阅器接口不兼容:UniSubscriber 与 MultiSubscriber 类型体系分离,Java 泛型无法自动推导 withSubscriber(...) 中的 S 类型边界。
✅ 正确做法是使用专为 Uni 设计的 UniAssertSubscriber(位于 io.smallrye.mutiny.test 包中),它实现了 UniSubscriber 接口,并提供链式断言方法:
@Test
public void shouldThrowAnErrorWhenUserIsNotFound() {
// 模拟仓库返回 nullItem,触发 map 中的异常分支
Mockito.when(userRepository.findById(Mockito.any()))
.thenReturn(Uni.createFrom().nullItem());
service.searchUser(new ObjectId())
.subscribe()
.withSubscriber(UniAssertSubscriber.create()) // ✅ 正确的 Subscriber 类型
.assertFailedWith(BusinessException.class, "Could not find an user with the given id.");
}⚠️ 注意事项:
- 确保引入了正确的依赖(Quarkus 测试默认包含 mutiny-test):
io.smallrye.reactive mutiny-test test - UniAssertSubscriber.create() 返回的是 UniAssertSubscriber
,支持泛型推导,无需显式声明类型; - assertFailedWith(Class
, String) 同时校验异常类型与消息内容,二者必须完全匹配(区分大小写与空格); - 若只需校验异常类型而忽略消息,可使用 assertFailedWith(BusinessException.class);
- 切勿混用 AssertSubscriber(用于 Multi)和 UniAssertSubscriber(仅用于 Uni),否则将触发编译期类型错误。
? 小结:Mutiny 的测试工具链严格区分流类型。对 Uni,始终选用 UniAssertSubscriber;其链式 API 简洁可靠,是验证异常路径最直接、最符合 Mutiny 最佳实践的方式。










