Skip to content

Commit a8a69be

Browse files
authored
Fix OTel JUnit5 Extension cleanup when using Nested test classes (#7999)
1 parent cbab60c commit a8a69be

3 files changed

Lines changed: 87 additions & 3 deletions

File tree

sdk/testing/src/main/java/io/opentelemetry/sdk/testing/junit5/OpenTelemetryExtension.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,8 @@ public void beforeAll(ExtensionContext context) {
196196
@Override
197197
public void afterAll(ExtensionContext context) {
198198
GlobalOpenTelemetry.resetForTest();
199-
openTelemetry.close();
199+
if (context.getParent().isPresent() && !context.getParent().get().getTestClass().isPresent()) {
200+
openTelemetry.close();
201+
}
200202
}
201203
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.sdk.testing.junit5;
7+
8+
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
9+
10+
import io.opentelemetry.api.trace.Tracer;
11+
import org.junit.jupiter.api.Nested;
12+
import org.junit.jupiter.api.Test;
13+
import org.junit.jupiter.api.extension.RegisterExtension;
14+
15+
class OpenTelemetryExtensionNestedTest {
16+
@RegisterExtension
17+
static final OpenTelemetryExtension otelTesting = OpenTelemetryExtension.create();
18+
19+
private final Tracer tracer = otelTesting.getOpenTelemetry().getTracer("test");
20+
21+
@Nested
22+
class FirstNestedClass {
23+
24+
@Test
25+
void recordSpan() {
26+
String testSpanName = "span-from-first-nested";
27+
tracer.spanBuilder(testSpanName).startSpan().end();
28+
29+
assertThat(otelTesting.getSpans())
30+
.singleElement()
31+
.satisfies(span -> assertThat(span.getName()).isEqualTo(testSpanName));
32+
}
33+
}
34+
35+
@Nested
36+
class SecondNestedClass {
37+
@Test
38+
void recordSpan() {
39+
String testSpanName = "span-from-second-nested";
40+
tracer.spanBuilder(testSpanName).startSpan().end();
41+
42+
assertThat(otelTesting.getSpans())
43+
.singleElement()
44+
.satisfies(span -> assertThat(span.getName()).isEqualTo(testSpanName));
45+
}
46+
}
47+
}

sdk/testing/src/test/java/io/opentelemetry/sdk/testing/junit5/OpenTelemetryExtensionTest.java

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
99
import static org.assertj.core.api.Assertions.assertThatThrownBy;
10+
import static org.mockito.Mockito.spy;
11+
import static org.mockito.Mockito.when;
1012

1113
import io.opentelemetry.api.GlobalOpenTelemetry;
1214
import io.opentelemetry.api.OpenTelemetry;
@@ -25,10 +27,12 @@
2527
import java.util.HashMap;
2628
import java.util.LinkedHashMap;
2729
import java.util.Map;
30+
import java.util.Optional;
2831
import java.util.concurrent.TimeUnit;
2932
import java.util.stream.Collectors;
3033
import javax.annotation.Nullable;
3134
import org.junit.jupiter.api.Test;
35+
import org.junit.jupiter.api.extension.ExtensionContext;
3236
import org.junit.jupiter.api.extension.RegisterExtension;
3337

3438
class OpenTelemetryExtensionTest {
@@ -219,7 +223,14 @@ public void getLogRecordsAgain() {
219223
void afterAll() {
220224
// Use a different instance of OpenTelemetryExtension to avoid interfering with other tests
221225
OpenTelemetryExtension extension = OpenTelemetryExtension.create();
222-
extension.beforeAll(null);
226+
227+
ExtensionContext parentContext = spy(ExtensionContext.class);
228+
when(parentContext.getTestClass()).thenReturn(Optional.empty());
229+
230+
ExtensionContext context = spy(ExtensionContext.class);
231+
when(context.getParent()).thenReturn(Optional.of(parentContext));
232+
233+
extension.beforeAll(context);
223234

224235
Meter meter = extension.getOpenTelemetry().getMeter("meter");
225236
Tracer tracer = extension.getOpenTelemetry().getTracer("tracer");
@@ -229,7 +240,7 @@ void afterAll() {
229240
assertThat(extension.getMetrics()).isNotEmpty();
230241
assertThat(extension.getSpans()).isNotEmpty();
231242

232-
extension.afterAll(null);
243+
extension.afterAll(context);
233244
assertThat(GlobalOpenTelemetry.get()).extracting("delegate").isSameAs(OpenTelemetry.noop());
234245

235246
meter.counterBuilder("counter").build().add(10);
@@ -238,6 +249,30 @@ void afterAll() {
238249
assertThat(extension.getSpans()).isEmpty();
239250
}
240251

252+
@Test
253+
void afterAllNestedOnly() {
254+
// Demonstrate specifically that Nested tests do not reset extension sdk
255+
OpenTelemetryExtension extension = OpenTelemetryExtension.create();
256+
257+
ExtensionContext context = spy(ExtensionContext.class);
258+
when(context.getParent()).thenReturn(Optional.empty());
259+
260+
extension.beforeAll(context);
261+
262+
Meter meter = extension.getOpenTelemetry().getMeter("meter");
263+
Tracer tracer = extension.getOpenTelemetry().getTracer("tracer");
264+
265+
extension.afterAll(context);
266+
267+
assertThat(GlobalOpenTelemetry.get()).extracting("delegate").isSameAs(OpenTelemetry.noop());
268+
269+
// GlobalTelemetry was reset, but extension's sdk was not closed
270+
meter.counterBuilder("counter").build().add(10);
271+
tracer.spanBuilder("span").startSpan().end();
272+
assertThat(extension.getMetrics()).isNotEmpty();
273+
assertThat(extension.getSpans()).isNotEmpty();
274+
}
275+
241276
@Test
242277
void baggageAndTracePropagation() {
243278
OpenTelemetryExtension extension = OpenTelemetryExtension.create();

0 commit comments

Comments
 (0)