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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 17:50:30