Skip to content

OpenTelemetryExtension closes SDK prematurely with JUnit 5 @Nested test classes #7919

@austince

Description

@austince

When using OpenTelemetryExtension with JUnit 5 @Nested test classes, the SDK is closed prematurely after the first nested class completes, causing subsequent nested classes to have non-functional metrics/spans/logs.

Root Cause

The afterAll() callback in OpenTelemetryExtension calls openTelemetry.close():

https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/junit5/OpenTelemetryExtension.java#L196-L199

@Override
public void afterAll(ExtensionContext context) {
  GlobalOpenTelemetry.resetForTest();
  openTelemetry.close();
}

In JUnit 5, @AfterAll (and thus afterAll() extension callbacks) is called after each nested class completes, not just once at the end of the outer test class. This means:

  1. First @Nested class runs → afterAll()openTelemetry.close() called
  2. Second @Nested class runs → SDK is already closed, metrics are not recorded
  3. Subsequent @Nested classes → Same issue

Reproduction

@DisplayName("My Test")
public class MyTest {

  @RegisterExtension
  static final OpenTelemetryExtension otelTesting = OpenTelemetryExtension.create();

  @Nested
  @DisplayName("First nested class")
  class FirstNestedTests {
    @Test
    void test1() {
      // This test works - metrics are recorded
      var meter = otelTesting.getOpenTelemetry().getMeter("test");
      var counter = meter.counterBuilder("test.counter").build();
      counter.add(1);

      assertThat(otelTesting.getMetrics()).isNotEmpty(); // PASSES
    }
  }

  @Nested
  @DisplayName("Second nested class")
  class SecondNestedTests {
    @Test
    void test2() {
      // This test fails - SDK was closed after FirstNestedTests
      var meter = otelTesting.getOpenTelemetry().getMeter("test");
      var counter = meter.counterBuilder("test.counter").build();
      counter.add(1);

      assertThat(otelTesting.getMetrics()).isNotEmpty(); // FAILS - metrics are empty
    }
  }
}

Workaround

Currently the only workaround is to use @TestClassOrder with @Order annotations to ensure test classes that depend on metrics run first:

@TestClassOrder(ClassOrderer.OrderAnnotation.class)
public class MyTest {

  @Nested
  @Order(1)  // Run first before SDK is closed
  class MetricsTests { ... }

  @Nested
  @Order(2)
  class OtherTests { ... }
}

This is pretty clunky though. It might also work to recreate the extension in each nested test, but that kind of defeats the purpose of nesting.

Environment

  • OpenTelemetry SDK version: 1.56.0
  • JUnit 5 version: 5.x / 6.x
  • Java version: 11+

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions