StepVerifier的recording特性工作原理及测试异常原因解析
StepVerifier recordWith 特性工作机制解析
问题场景
以下测试代码执行时出现断言失败:
import org.junit.jupiter.api.Test; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import reactor.core.publisher.Flux; import reactor.test.StepVerifier; import java.util.ArrayList; import java.util.List; public class StepVerifierTest { @Test void test() { List<GrantedAuthority> roles = List.of( new SimpleGrantedAuthority("user"), new SimpleGrantedAuthority("admin") ); StepVerifier.create(Flux.fromIterable(roles).map(GrantedAuthority.class::cast)) .recordWith(ArrayList::new) .expectRecordedMatches(actualRoles -> actualRoles.containsAll(roles)) .expectComplete() .verify(); } }
错误信息:
java.lang.AssertionError: expectation "expectRecordedMatches" failed (expected collection predicate match; actual: [user])
疑问点:文档说明recordWith会存储Subscriber.onNext(Object)的所有值,但测试仅第一个元素被存入集合就执行了断言,预期流耗尽后再检查断言,且API未提示需手动控制记录时机。
recordWith 核心工作机制
recordWith的作用是创建一个集合,持续记录后续所有onNext事件的元素,但断言的执行时机由调用顺序决定。- StepVerifier的断言逻辑是按代码调用顺序逐个触发:当你调用
expectRecordedMatches时,它会立即检查当前集合中已记录的元素,不会主动等待整个流推送完成。 - 你的代码中,
expectRecordedMatches紧跟在recordWith之后,此时流仅推送了第一个元素user,断言就被触发执行,自然无法匹配包含两个元素的预期集合。 - 只有先通过其他步骤(比如
expectNextCount(2)、逐个expectNext)让流推送完所有元素,再调用expectRecordedMatches,集合才会包含所有onNext元素,断言才能正确执行。
简单来说,recordWith会全程记录元素,但断言不会自动等待流结束,必须先确保所有元素都被推送记录后,再执行断言检查。
内容的提问来源于stack exchange,提问作者Sergey Zolotarev
相关产品推荐
相关产品推荐

