首页 > 解决方案 > 使用 SpringBootTest 时如何在控制器中使用 span 初始化默认跟踪上下文

问题描述

我正在从 Spring Boot 1.5.21 迁移到 2.2.5,并且在此过程中还从 spring-boot-cloud 版本 Edgware.SR6 迁移到 Hoxton.SR3。这一举动迫使我放弃了侦探自己的跟踪器/跨度模型实现,并接受了勇敢的新模型。但是,我的控制器集成测试存在问题。

我有一个调用Edge主类的微服务EdgeApplication,我使用 Spock 作为测试框架。我的代码包括以下测试类:

@ContextConfiguration(classes = EdgeApplication.class)
@SpringBootTest(classes = EdgeApplication.class)
@ActiveProfiles(profiles = ["test"])
@AutoConfigureMockMvc
class VerificationCodeControllerSpecIT extends Specification {

  @Autowired
  MockMvc mockMvc

  def setup() {
     mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build()
  }

  def "Generate change password verification code"() {
    // Some code calling a PrincipalController via mockMvc.perform()
  }
}

以前,在 Spring Boot 1.5.21 中,当调用到达 时PrincipalController,会初始化一个带有 span 的默认跟踪上下文。现在,在 Spring Boot 2 中,情况并非如此。我必须强调,这种缺乏上下文的情况PrincipalController只发生在测试代码中,而不是在微服务的实际运行中。

为什么这种行为发生了变化,我怎样才能恢复旧的行为,即在调用控制器时有一个带有 span 的默认跟踪上下文?

我添加了一个演示项目: 演示 您将能够运行集成测试并在调试中看到控制器tracer.currentSpan()中为空(同时包含正常项目运行的值)

标签: spring-bootgroovyspring-boot-testspring-cloud-sleuth

解决方案


在 Spring Boot 1.5.21 中,spring-cloud-sleuth 的最新支持版本是 1.3.6.RELEASE。

在旧版本中,Sleuth 曾经有拦截器:'TraceHandlerInterceptor',用于在 Servlet 调度程序触发此拦截器时创建一个 span。

在版本 1.5.21 上运行 Spring Boot 测试时,触发上述拦截器的 MockMvc init TestDispatcherServlet。

作为与 Brave 对齐的 HTTP 检测的一部分,此拦截器已被删除。

使用 MockMvc 时,必须显式配置您的过滤器链。您的 MockMvc 缺少 TracingFilter


推荐阅读