Skip to content

Commit 16a300a

Browse files
test: Add unit tests for MDC propagation in DubboServer/ClientTracingObservationHandler
1 parent c4dbab0 commit 16a300a

2 files changed

Lines changed: 178 additions & 0 deletions

File tree

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.dubbo.tracing.handler;
18+
19+
import org.apache.dubbo.tracing.context.DubboClientContext;
20+
21+
import io.micrometer.tracing.CurrentTraceContext;
22+
import io.micrometer.tracing.TraceContext;
23+
import io.micrometer.tracing.Tracer;
24+
import org.junit.jupiter.api.AfterEach;
25+
import org.junit.jupiter.api.BeforeEach;
26+
import org.junit.jupiter.api.Test;
27+
import org.mockito.Mockito;
28+
import org.slf4j.MDC;
29+
30+
import static org.junit.jupiter.api.Assertions.assertEquals;
31+
import static org.junit.jupiter.api.Assertions.assertNull;
32+
import static org.mockito.Mockito.when;
33+
34+
class DubboClientTracingObservationHandlerTest {
35+
36+
private Tracer mockTracer;
37+
private CurrentTraceContext mockCurrentTraceContext;
38+
private TraceContext mockTraceContext;
39+
private DubboClientContext mockContext;
40+
private DubboClientTracingObservationHandler<DubboClientContext> handler;
41+
42+
@BeforeEach
43+
void setUp() {
44+
// Clear MDC before each test to ensure a clean state
45+
MDC.clear();
46+
47+
mockTracer = Mockito.mock(Tracer.class);
48+
mockCurrentTraceContext = Mockito.mock(CurrentTraceContext.class);
49+
mockTraceContext = Mockito.mock(TraceContext.class);
50+
mockContext = Mockito.mock(DubboClientContext.class);
51+
52+
when(mockTracer.currentTraceContext()).thenReturn(mockCurrentTraceContext);
53+
when(mockCurrentTraceContext.context()).thenReturn(mockTraceContext);
54+
when(mockTraceContext.traceId()).thenReturn("mock-trace-id-123");
55+
when(mockTraceContext.spanId()).thenReturn("mock-span-id-456");
56+
57+
handler = new DubboClientTracingObservationHandler<>(mockTracer);
58+
}
59+
60+
@AfterEach
61+
void tearDown() {
62+
MDC.clear();
63+
}
64+
65+
@Test
66+
void proveWorking_WhenScopeOpens_MdcShouldHaveIds() {
67+
// 1. Verify MDC is currently empty
68+
assertNull(MDC.get("traceId"));
69+
assertNull(MDC.get("spanId"));
70+
71+
handler.onScopeOpened(mockContext);
72+
73+
assertEquals("mock-trace-id-123", MDC.get("traceId"), "Trace ID should be mapped to MDC!");
74+
assertEquals("mock-span-id-456", MDC.get("spanId"), "Span ID should be mapped to MDC!");
75+
}
76+
77+
@Test
78+
void proveFailurePrevention_WhenScopeCloses_MdcShouldBeCleaned() {
79+
handler.onScopeOpened(mockContext);
80+
assertEquals("mock-trace-id-123", MDC.get("traceId"));
81+
82+
handler.onScopeClosed(mockContext);
83+
84+
// PROOF THE LEAK IS PREVENTED: MDC must be completely empty now.
85+
assertNull(MDC.get("traceId"), "Trace ID leaked! It was not removed when scope closed.");
86+
assertNull(MDC.get("spanId"), "Span ID leaked! It was not removed when scope closed.");
87+
}
88+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.dubbo.tracing.handler;
18+
19+
import org.apache.dubbo.rpc.RpcContext;
20+
import org.apache.dubbo.tracing.context.DubboServerContext;
21+
22+
import io.micrometer.tracing.CurrentTraceContext;
23+
import io.micrometer.tracing.TraceContext;
24+
import io.micrometer.tracing.Tracer;
25+
import org.junit.jupiter.api.AfterEach;
26+
import org.junit.jupiter.api.BeforeEach;
27+
import org.junit.jupiter.api.Test;
28+
import org.mockito.Mockito;
29+
import org.slf4j.MDC;
30+
31+
import static org.junit.jupiter.api.Assertions.assertEquals;
32+
import static org.junit.jupiter.api.Assertions.assertNull;
33+
import static org.mockito.Mockito.when;
34+
35+
class DubboServerTracingObservationHandlerTest {
36+
37+
private Tracer mockTracer;
38+
private CurrentTraceContext mockCurrentTraceContext;
39+
private TraceContext mockTraceContext;
40+
private DubboServerContext mockContext;
41+
private DubboServerTracingObservationHandler<DubboServerContext> handler;
42+
43+
@BeforeEach
44+
void setUp() {
45+
// Clear MDC before each test to ensure a clean state
46+
MDC.clear();
47+
48+
mockTracer = Mockito.mock(Tracer.class);
49+
mockCurrentTraceContext = Mockito.mock(CurrentTraceContext.class);
50+
mockTraceContext = Mockito.mock(TraceContext.class);
51+
mockContext = Mockito.mock(DubboServerContext.class);
52+
53+
when(mockTracer.currentTraceContext()).thenReturn(mockCurrentTraceContext);
54+
when(mockCurrentTraceContext.context()).thenReturn(mockTraceContext);
55+
when(mockTraceContext.traceId()).thenReturn("mock-trace-id-123");
56+
when(mockTraceContext.spanId()).thenReturn("mock-span-id-456");
57+
58+
handler = new DubboServerTracingObservationHandler<>(mockTracer);
59+
}
60+
61+
@AfterEach
62+
void tearDown() {
63+
MDC.clear();
64+
RpcContext.removeServerContext();
65+
}
66+
67+
@Test
68+
void proveWorking_WhenScopeOpens_MdcShouldHaveIds() {
69+
// 1. Verify MDC is currently empty
70+
assertNull(MDC.get("traceId"));
71+
assertNull(MDC.get("spanId"));
72+
73+
handler.onScopeOpened(mockContext);
74+
75+
assertEquals("mock-trace-id-123", MDC.get("traceId"), "Trace ID should be mapped to MDC!");
76+
assertEquals("mock-span-id-456", MDC.get("spanId"), "Span ID should be mapped to MDC!");
77+
}
78+
79+
@Test
80+
void proveFailurePrevention_WhenScopeCloses_MdcShouldBeCleaned() {
81+
handler.onScopeOpened(mockContext);
82+
assertEquals("mock-trace-id-123", MDC.get("traceId"));
83+
84+
handler.onScopeClosed(mockContext);
85+
86+
// PROOF THE LEAK IS PREVENTED: MDC must be completely empty now.
87+
assertNull(MDC.get("traceId"), "Trace ID leaked! It was not removed when scope closed.");
88+
assertNull(MDC.get("spanId"), "Span ID leaked! It was not removed when scope closed.");
89+
}
90+
}

0 commit comments

Comments
 (0)