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

添加spring-cloud-starter-sleuth后Spring Boot Rest Doc测试失败求助

解决Spring Boot WebFlux RestDocs测试加Sleuth后上下文提前关闭的问题

我之前也碰到过类似的棘手问题,结合你的场景来看,核心矛盾是批量测试时的Spring上下文复用冲突,再加上Sleuth对上下文生命周期的额外影响,导致部分测试在上下文被关闭后仍试图调用它。下面是具体的分析和可落地的解决方案:

问题根源拆解

  1. JUnit 5并行测试的干扰:Maven Surefire插件默认可能开启了并行执行(尤其是新版本),当多个测试类共享同一个Spring上下文时,Sleuth注入的链路追踪Bean会打乱生命周期——某一个测试结束后触发了上下文关闭,其他测试却还在复用这个已失效的上下文。
  2. 上下文缓存的Key冲突:Sleuth会修改上下文的Bean定义(比如添加TraceFilter等组件),导致不同测试类的上下文缓存Key被错误判定为相同,进而复用了已经被某个测试关闭的上下文。
  3. 不同OS的线程调度差异:Windows和Linux的线程调度策略不同,导致不同测试类先执行完毕并触发上下文关闭,这就是为什么不同环境下失败的测试类不一样。

分步解决方案

1. 先禁用测试并行执行(快速验证)

首先验证是不是并行执行导致的问题,在pom.xml中配置Maven Surefire插件关闭并行:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.22.2</version>
    <configuration>
        <parallel>none</parallel>
        <useUnlimitedThreads>false</useUnlimitedThreads>
        <!-- 确保对JUnit 5的支持 -->
        <providerSelection>junit-platform</providerSelection>
    </configuration>
</plugin>

运行mvn test看看问题是否消失,如果解决了,说明并行执行是主要诱因。

2. 强制每个测试类使用独立上下文(保留并行的情况下)

如果需要保持测试并行执行,可以给每个RestDocs测试类添加@DirtiesContext注解,让Spring在每个测试类结束后销毁对应的上下文,避免复用冲突:

@ExtendWith({ RestDocumentationExtension.class, SpringExtension.class })
@AutoConfigureRestDocs("target/generated-snippets")
@SpringBootTest(classes = ArchimedesApplication.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) // 添加这一行
class OptControllerDocTest {
    // ... 你的测试代码
}

这个注解会告诉Spring测试框架:当前测试类会"污染"上下文,测试结束后必须销毁它。这样每个测试类都拥有独立的上下文,不会互相干扰。

3. 调整Sleuth的自动配置(如果不需要测试链路追踪)

如果你的RestDocs测试不需要验证链路追踪功能,可以在测试中排除Sleuth的WebFlux相关自动配置,减少对上下文的干扰:

@SpringBootTest(
    classes = ArchimedesApplication.class,
    exclude = {SleuthWebFluxAutoConfiguration.class, TraceWebFilterAutoConfiguration.class}
)

这样Sleuth就不会给WebFlux添加额外的过滤器和Bean,从源头避免上下文生命周期异常。

4. 升级依赖版本(彻底解决潜在Bug)

你使用的Spring Boot 2.1.4和Sleuth 2.1.1都是比较老旧的版本,存在一些已知的上下文生命周期管理Bug。建议升级到对应分支的最新稳定版:

  • Spring Boot升级到2.1.18.RELEASE(2.1.x分支的最后一个稳定版)
  • Spring Cloud Sleuth升级到2.1.9.RELEASE(与Spring Boot 2.1.x兼容的最新版)
    新版本修复了很多测试上下文相关的问题,可能从根源上解决这个冲突。

5. 临时Workaround:确保上下文活跃再构建WebTestClient

如果以上方法都暂时无法实施,可以在@BeforeEach中检查上下文是否活跃,必要时重新刷新:

@BeforeEach
void beforeEach(RestDocumentationContextProvider restDocumentation) {
    ConfigurableApplicationContext configurableContext = (ConfigurableApplicationContext) context;
    if (!configurableContext.isActive()) {
        configurableContext.refresh();
    }
    this.webTestClient = WebTestClient.bindToApplicationContext(context)
            .configureClient()
            .filter(documentationConfiguration(restDocumentation))
            .build();
}

不过这只是临时的补救措施,还是建议从前面的方案中选择彻底解决的方式。


内容的提问来源于stack exchange,提问作者Florian E.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:11:21