迁移到Spring Boot 3并从Sleuth重构到Micrometer后,我不再能够使用WebTestClient + Tracer测试traceId传播。
我在这里的测试是有一个简单的@RestController,我希望traceId通过跟踪器传播:
@RestController
class MyTraceIdController(@Autowired private val tracer: Tracer) {
@GetMapping("/trace")
fun info(): ResponseEntity<String> {
val traceKey = "x-b3-traceid"
// Using tracer the traceId is retrieved at runtime but not during test
val responseHeaders = HttpHeaders()
responseHeaders.set(traceKey, tracer.currentSpan()?.context()?.traceId().toString())
return ResponseEntity
.ok()
.headers(responseHeaders)
.body("OK")
}
}
我们的目标是通过WebTestClient来测试它:
@AutoConfigureWebTestClient
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
class MyTraceIdTests(@Autowired private val webTestClient: WebTestClient) {
@Test
fun `Assert info endpoint works as expected with webTestClient`() {
val traceKey = "x-b3-traceid"
val traceValue = "463ac35c9f6413ad48485a3953bb6124"
val spanKey = "x-b3-spanid"
val spanValue = "a2fb4a1d1a96d312"
webTestClient.get()
.uri("http://localhost:9080/trace")
.header(traceKey, traceValue)
.header(spanKey, spanValue)
.exchange()
.expectStatus().isOk
.expectHeader().valueEquals(traceKey, traceValue)
.expectBody<String>().isEqualTo("OK")
}
}
对于Sleuth,在运行测试时,注入的BraveTracer完美地完成了传播traceId的工作。
与Micrometer,我不能再有一个正确的示踪剂注入做这项工作。
为了测试这个案例,我创建了以下示例: https://github.com/bvoglevette/trace-id-sample
两个行为是可观察的:
在<<ul>我尝试过的不同方法都没有成功
- 使用SimpleTracer() 要实现我自己的Tracer bean,请遵循Micrometer文档
- 在我的测试中使用BraveAutoconfiguration或基于它实例化bean
这些实现都不能产生一个传播traceId的bean。
我更希望找到一种方法来简单地注入来自BraveAutoconfiguration的工作bean。我错过了什么?我应该改变我的测试方式吗?
您需要在您的测试类中添加@AutoConfigureObservability
。默认情况下,测试中的可观察性是禁用的。
我还将我的spring-web和spring-integration应用程序从spring boot 2 sleuth迁移到spring boot 3 with micrometer,也遇到了问题。我想手动配置跟踪,而且我没有访问所有模块中的执行器)。
为了手动配置跟踪,除了普通的微米依赖,我需要添加这两个:微米跟踪-测试和微米跟踪-集成测试(注意:在大多数情况下,您可能只需要微米跟踪-测试):
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bom</artifactId>
<version>${micrometer.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>context-propagation</artifactId>
<version>${micrometer.version}</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-test</artifactId>
<version>${micrometer.version}</version>
<scope>test</scope> (!)
<exclusions>
<exclusion>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-jre8-standalone</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-integration-test</artifactId>
<version>${micrometer.version}</version>
<scope>test</scope> (!)
<exclusions>
<exclusion>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-jre8-standalone</artifactId>
</exclusion>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
之后,我提供了SimpleTracer bean来测试上下文(这是用于测试的Tracer实现)并手动设置观察注册表(TestObservationRegistry)。我用观察处理程序DefaultTracingObservationHandler配置了注册表,它委托给这个测试SimpleTracer:
@Bean
SimpleTracer simpleTracer() {
return new SimpleTracer();
}
@Bean
TestObservationRegistry observationRegistry(SimpleTracer tracer) {
final TestObservationRegistry testObservationRegistry = TestObservationRegistry.create();
testObservationRegistry.observationConfig().observationHandler(new DefaultTracingObservationHandler(tracer));
return testObservationRegistry;
}
注意:如果在您的测试中,您得到如下的异常,那么您没有配置观察处理程序,即您的观察注册表不包含跟踪观察处理程序。在这种情况下,请尝试手动添加观察处理程序(参见上面的示例)。
java.lang.IllegalArgumentException: Context does not have an entry for key [class io.micrometer.tracing.handler.TracingObservationHandler$TracingContext]
at io.micrometer.observation.Observation$Context.getRequired(Observation.java:928)
at micrometer.tracing@1.0.2/io.micrometer.tracing.handler.TracingAwareMeterObservationHandler.onStop(TracingAwareMeterObservationHandler.java:79)
at io.micrometer.observation.ObservationHandler$FirstMatchingCompositeObservationHandler.lambda$onStop$7(ObservationHandler.java:173)