Skip to content

Commit b2d1c61

Browse files
committed
Remove reflection to make tests more stable
See spring-projectsgh-30156
1 parent 7e369be commit b2d1c61

File tree

1 file changed

+118
-47
lines changed

1 file changed

+118
-47
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/TracingAutoConfigurationTests.java

+118-47
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,29 @@
1616

1717
package org.springframework.boot.actuate.autoconfigure.metrics;
1818

19-
import java.lang.reflect.Method;
20-
import java.util.Collection;
19+
import java.util.ArrayList;
2120
import java.util.List;
2221

2322
import io.micrometer.core.instrument.observation.MeterObservationHandler;
23+
import io.micrometer.core.instrument.observation.Observation;
2424
import io.micrometer.core.instrument.observation.Observation.Context;
2525
import io.micrometer.core.instrument.observation.ObservationHandler;
2626
import io.micrometer.core.instrument.observation.ObservationHandler.AllMatchingCompositeObservationHandler;
27-
import io.micrometer.core.instrument.observation.ObservationHandler.CompositeObservationHandler;
2827
import io.micrometer.core.instrument.observation.ObservationHandler.FirstMatchingCompositeObservationHandler;
2928
import io.micrometer.core.instrument.observation.ObservationRegistry;
30-
import io.micrometer.core.instrument.observation.ObservationRegistry.ObservationConfig;
31-
import io.micrometer.core.instrument.observation.TimerObservationHandler;
3229
import io.micrometer.tracing.Tracer;
33-
import io.micrometer.tracing.handler.DefaultTracingObservationHandler;
30+
import io.micrometer.tracing.handler.TracingObservationHandler;
3431
import org.junit.jupiter.api.Test;
32+
import org.mockito.Answers;
3533
import org.mockito.Mockito;
3634

3735
import org.springframework.boot.actuate.autoconfigure.metrics.test.MetricsRun;
3836
import org.springframework.boot.autoconfigure.AutoConfigurations;
3937
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
4038
import org.springframework.context.annotation.Bean;
4139
import org.springframework.context.annotation.Configuration;
40+
import org.springframework.context.annotation.Import;
4241
import org.springframework.core.annotation.Order;
43-
import org.springframework.util.ReflectionUtils;
4442

4543
import static org.assertj.core.api.Assertions.assertThat;
4644

@@ -55,55 +53,51 @@ class TracingAutoConfigurationTests {
5553
.withConfiguration(AutoConfigurations.of(TracingAutoConfiguration.class));
5654

5755
@Test
58-
@SuppressWarnings("rawtypes")
5956
void autoConfiguresObservationHandler() {
6057
this.contextRunner.withUserConfiguration(ObservationHandlers.class).run((context) -> {
6158
ObservationRegistry observationRegistry = context.getBean(ObservationRegistry.class);
62-
List<ObservationHandler<?>> handlers = getObservationHandlers(observationRegistry);
63-
assertThat(handlers).hasSize(6);
64-
assertThat(handlers.get(0)).isInstanceOf(TimerObservationHandler.class);
65-
assertThat(handlers.get(1)).isInstanceOf(CustomObservationHandler.class);
66-
assertThat(handlers.get(2)).isInstanceOf(FirstMatchingCompositeObservationHandler.class);
67-
assertThat(handlers.get(3)).isInstanceOf(AllMatchingCompositeObservationHandler.class);
68-
// CustomMeterObservationHandlers get wrapped into a
69-
// FirstMatchingCompositeObservationHandler
70-
assertThat(handlers.get(4)).isInstanceOf(FirstMatchingCompositeObservationHandler.class);
71-
List<ObservationHandler> containedHandlers = ((CompositeObservationHandler) handlers.get(4)).getHandlers();
72-
assertThat(containedHandlers).hasSize(2);
73-
assertThat(containedHandlers.get(0)).isInstanceOf(CustomMeterObservationHandler.class);
74-
assertThat(containedHandlers.get(1)).isInstanceOf(CustomMeterObservationHandler.class);
75-
assertThat(handlers.get(4)).isInstanceOf(FirstMatchingCompositeObservationHandler.class);
76-
// DefaultTracingObservationHandler get wrapped into a
77-
// FirstMatchingCompositeObservationHandler
78-
containedHandlers = ((CompositeObservationHandler) handlers.get(5)).getHandlers();
79-
assertThat(containedHandlers).hasSize(2);
80-
assertThat(containedHandlers.get(0)).isInstanceOf(DefaultTracingObservationHandler.class);
81-
assertThat(containedHandlers.get(1)).isInstanceOf(DefaultTracingObservationHandler.class);
82-
59+
List<ObservationHandler<?>> handlers = context.getBean(CalledHandlers.class).getCalledHandlers();
60+
Observation.start("test-observation", observationRegistry);
61+
assertThat(handlers).hasSize(3);
62+
// Regular handlers are registered first
63+
assertThat(handlers.get(0)).isInstanceOf(CustomObservationHandler.class);
64+
// Multiple MeterObservationHandler are wrapped in
65+
// FirstMatchingCompositeObservationHandler, which calls only the first one
66+
assertThat(handlers.get(1)).isInstanceOf(CustomMeterObservationHandler.class);
67+
assertThat(((CustomMeterObservationHandler) handlers.get(1)).getName())
68+
.isEqualTo("customMeterObservationHandler1");
69+
// Multiple TracingObservationHandler are wrapped in
70+
// FirstMatchingCompositeObservationHandler, which calls only the first one
71+
assertThat(handlers.get(2)).isInstanceOf(CustomTracingObservationHandler.class);
72+
assertThat(((CustomTracingObservationHandler) handlers.get(2)).getName())
73+
.isEqualTo("customTracingHandler1");
8374
});
8475
}
8576

86-
@SuppressWarnings("unchecked")
87-
private List<ObservationHandler<?>> getObservationHandlers(ObservationRegistry registry) {
88-
Method method = ReflectionUtils.findMethod(ObservationConfig.class, "getObservationHandlers");
89-
ReflectionUtils.makeAccessible(method);
90-
return List.copyOf(
91-
(Collection<ObservationHandler<?>>) ReflectionUtils.invokeMethod(method, registry.observationConfig()));
77+
@Configuration(proxyBeanMethods = false)
78+
static class CalledHandlersConfiguration {
79+
80+
@Bean
81+
CalledHandlers calledHandlers() {
82+
return new CalledHandlers();
83+
}
84+
9285
}
9386

9487
@Configuration(proxyBeanMethods = false)
88+
@Import(CalledHandlersConfiguration.class)
9589
static class ObservationHandlers {
9690

9791
@Bean
9892
@Order(6)
99-
DefaultTracingObservationHandler customTracingHandler2() {
100-
return new DefaultTracingObservationHandler(Mockito.mock(Tracer.class));
93+
CustomTracingObservationHandler customTracingHandler2(CalledHandlers calledHandlers) {
94+
return new CustomTracingObservationHandler("customTracingHandler2", calledHandlers);
10195
}
10296

10397
@Bean
10498
@Order(5)
105-
DefaultTracingObservationHandler customTracingHandler1() {
106-
return new DefaultTracingObservationHandler(Mockito.mock(Tracer.class));
99+
CustomTracingObservationHandler customTracingHandler1(CalledHandlers calledHandlers) {
100+
return new CustomTracingObservationHandler("customTracingHandler1", calledHandlers);
107101
}
108102

109103
@Bean
@@ -120,25 +114,84 @@ FirstMatchingCompositeObservationHandler customFirstMatchingCompositeObservation
120114

121115
@Bean
122116
@Order(2)
123-
ObservationHandler<Context> customObservationHandler() {
124-
return new CustomObservationHandler();
117+
ObservationHandler<Context> customObservationHandler(CalledHandlers calledHandlers) {
118+
return new CustomObservationHandler(calledHandlers);
125119
}
126120

127121
@Bean
128122
@Order(1)
129-
MeterObservationHandler<Context> customMeterObservationHandler2() {
130-
return new CustomMeterObservationHandler();
123+
MeterObservationHandler<Context> customMeterObservationHandler2(CalledHandlers calledHandlers) {
124+
return new CustomMeterObservationHandler("customMeterObservationHandler2", calledHandlers);
131125
}
132126

133127
@Bean
134128
@Order(0)
135-
MeterObservationHandler<Context> customMeterObservationHandler1() {
136-
return new CustomMeterObservationHandler();
129+
MeterObservationHandler<Context> customMeterObservationHandler1(CalledHandlers calledHandlers) {
130+
return new CustomMeterObservationHandler("customMeterObservationHandler1", calledHandlers);
131+
}
132+
133+
}
134+
135+
private static class CalledHandlers {
136+
137+
private final List<ObservationHandler<?>> calledHandlers = new ArrayList<>();
138+
139+
void onCalled(ObservationHandler<?> handler) {
140+
this.calledHandlers.add(handler);
141+
}
142+
143+
List<ObservationHandler<?>> getCalledHandlers() {
144+
return this.calledHandlers;
145+
}
146+
147+
}
148+
149+
private static class CustomTracingObservationHandler implements TracingObservationHandler<Context> {
150+
151+
private final Tracer tracer = Mockito.mock(Tracer.class, Answers.RETURNS_MOCKS);
152+
153+
private final String name;
154+
155+
private final CalledHandlers calledHandlers;
156+
157+
CustomTracingObservationHandler(String name, CalledHandlers calledHandlers) {
158+
this.name = name;
159+
this.calledHandlers = calledHandlers;
160+
}
161+
162+
String getName() {
163+
return this.name;
164+
}
165+
166+
@Override
167+
public Tracer getTracer() {
168+
return this.tracer;
169+
}
170+
171+
@Override
172+
public void onStart(Context context) {
173+
this.calledHandlers.onCalled(this);
174+
}
175+
176+
@Override
177+
public boolean supportsContext(Context context) {
178+
return true;
137179
}
138180

139181
}
140182

141-
static class CustomObservationHandler implements ObservationHandler<Context> {
183+
private static class CustomObservationHandler implements ObservationHandler<Context> {
184+
185+
private final CalledHandlers calledHandlers;
186+
187+
CustomObservationHandler(CalledHandlers calledHandlers) {
188+
this.calledHandlers = calledHandlers;
189+
}
190+
191+
@Override
192+
public void onStart(Context context) {
193+
this.calledHandlers.onCalled(this);
194+
}
142195

143196
@Override
144197
public boolean supportsContext(Context context) {
@@ -147,7 +200,25 @@ public boolean supportsContext(Context context) {
147200

148201
}
149202

150-
static class CustomMeterObservationHandler implements MeterObservationHandler<Context> {
203+
private static class CustomMeterObservationHandler implements MeterObservationHandler<Context> {
204+
205+
private final CalledHandlers calledHandlers;
206+
207+
private final String name;
208+
209+
CustomMeterObservationHandler(String name, CalledHandlers calledHandlers) {
210+
this.name = name;
211+
this.calledHandlers = calledHandlers;
212+
}
213+
214+
String getName() {
215+
return this.name;
216+
}
217+
218+
@Override
219+
public void onStart(Context context) {
220+
this.calledHandlers.onCalled(this);
221+
}
151222

152223
@Override
153224
public boolean supportsContext(Context context) {

0 commit comments

Comments
 (0)