Skip to content

Commit 270af1e

Browse files
committed
Remove reflection to make tests more stable
See spring-projectsgh-30156
1 parent 03e059d commit 270af1e

File tree

1 file changed

+118
-46
lines changed

1 file changed

+118
-46
lines changed

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

Lines changed: 118 additions & 46 deletions
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

@@ -59,51 +57,48 @@ class TracingAutoConfigurationTests {
5957
void autoConfiguresObservationHandler() {
6058
this.contextRunner.withUserConfiguration(ObservationHandlers.class).run((context) -> {
6159
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-
60+
List<ObservationHandler<?>> handlers = context.getBean(CalledHandlers.class).getCalledHandlers();
61+
Observation.start("test-observation", observationRegistry);
62+
assertThat(handlers).hasSize(3);
63+
// Regular handlers are registered first
64+
assertThat(handlers.get(0)).isInstanceOf(CustomObservationHandler.class);
65+
// Multiple MeterObservationHandler are wrapped in
66+
// FirstMatchingCompositeObservationHandler, which calls only the first one
67+
assertThat(handlers.get(1)).isInstanceOf(CustomMeterObservationHandler.class);
68+
assertThat(((CustomMeterObservationHandler) handlers.get(1)).getName())
69+
.isEqualTo("customMeterObservationHandler1");
70+
// Multiple TracingObservationHandler are wrapped in
71+
// FirstMatchingCompositeObservationHandler, which calls only the first one
72+
assertThat(handlers.get(2)).isInstanceOf(CustomTracingObservationHandler.class);
73+
assertThat(((CustomTracingObservationHandler) handlers.get(2)).getName())
74+
.isEqualTo("customTracingHandler1");
8375
});
8476
}
8577

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()));
78+
@Configuration(proxyBeanMethods = false)
79+
static class CalledHandlersConfiguration {
80+
81+
@Bean
82+
CalledHandlers calledHandlers() {
83+
return new CalledHandlers();
84+
}
85+
9286
}
9387

9488
@Configuration(proxyBeanMethods = false)
89+
@Import(CalledHandlersConfiguration.class)
9590
static class ObservationHandlers {
9691

9792
@Bean
9893
@Order(6)
99-
DefaultTracingObservationHandler customTracingHandler2() {
100-
return new DefaultTracingObservationHandler(Mockito.mock(Tracer.class));
94+
CustomTracingObservationHandler customTracingHandler2(CalledHandlers calledHandlers) {
95+
return new CustomTracingObservationHandler("customTracingHandler2", calledHandlers);
10196
}
10297

10398
@Bean
10499
@Order(5)
105-
DefaultTracingObservationHandler customTracingHandler1() {
106-
return new DefaultTracingObservationHandler(Mockito.mock(Tracer.class));
100+
CustomTracingObservationHandler customTracingHandler1(CalledHandlers calledHandlers) {
101+
return new CustomTracingObservationHandler("customTracingHandler1", calledHandlers);
107102
}
108103

109104
@Bean
@@ -120,25 +115,84 @@ FirstMatchingCompositeObservationHandler customFirstMatchingCompositeObservation
120115

121116
@Bean
122117
@Order(2)
123-
ObservationHandler<Context> customObservationHandler() {
124-
return new CustomObservationHandler();
118+
ObservationHandler<Context> customObservationHandler(CalledHandlers calledHandlers) {
119+
return new CustomObservationHandler(calledHandlers);
125120
}
126121

127122
@Bean
128123
@Order(1)
129-
MeterObservationHandler<Context> customMeterObservationHandler2() {
130-
return new CustomMeterObservationHandler();
124+
MeterObservationHandler<Context> customMeterObservationHandler2(CalledHandlers calledHandlers) {
125+
return new CustomMeterObservationHandler("customMeterObservationHandler2", calledHandlers);
131126
}
132127

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

139182
}
140183

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

143197
@Override
144198
public boolean supportsContext(Context context) {
@@ -147,7 +201,25 @@ public boolean supportsContext(Context context) {
147201

148202
}
149203

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

152224
@Override
153225
public boolean supportsContext(Context context) {

0 commit comments

Comments
 (0)