diff --git a/framework-docs/modules/ROOT/pages/testing/testcontext-framework/tel-config.adoc b/framework-docs/modules/ROOT/pages/testing/testcontext-framework/tel-config.adoc index 3bb86387d393..2c2c749b88cb 100644 --- a/framework-docs/modules/ROOT/pages/testing/testcontext-framework/tel-config.adoc +++ b/framework-docs/modules/ROOT/pages/testing/testcontext-framework/tel-config.adoc @@ -12,6 +12,8 @@ by default, exactly in the following order: xref:testing/testcontext-framework/application-events.adoc[`ApplicationEvents`]. * `DependencyInjectionTestExecutionListener`: Provides dependency injection for the test instance. +* `MicrometerObservationRegistryTestExecutionListener`: Provides support for + Micrometer's `ObservationRegistry`. * `DirtiesContextTestExecutionListener`: Handles the `@DirtiesContext` annotation for "`after`" modes. * `TransactionalTestExecutionListener`: Provides transactional test execution with diff --git a/spring-test/src/main/java/org/springframework/test/context/TestExecutionListener.java b/spring-test/src/main/java/org/springframework/test/context/TestExecutionListener.java index fc4ea1187a5d..a90c378d6d92 100644 --- a/spring-test/src/main/java/org/springframework/test/context/TestExecutionListener.java +++ b/spring-test/src/main/java/org/springframework/test/context/TestExecutionListener.java @@ -68,6 +68,8 @@ * ApplicationEventsTestExecutionListener} *
  • {@link org.springframework.test.context.support.DependencyInjectionTestExecutionListener * DependencyInjectionTestExecutionListener}
  • + *
  • {@link org.springframework.test.context.observation.MicrometerObservationRegistryTestExecutionListener + * MicrometerObservationRegistryTestExecutionListener}
  • *
  • {@link org.springframework.test.context.support.DirtiesContextTestExecutionListener * DirtiesContextTestExecutionListener}
  • *
  • {@link org.springframework.test.context.transaction.TransactionalTestExecutionListener diff --git a/spring-test/src/main/java/org/springframework/test/context/observation/MicrometerObservationRegistryTestExecutionListener.java b/spring-test/src/main/java/org/springframework/test/context/observation/MicrometerObservationRegistryTestExecutionListener.java new file mode 100644 index 000000000000..97873c1a097f --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/context/observation/MicrometerObservationRegistryTestExecutionListener.java @@ -0,0 +1,142 @@ +/* + * Copyright 2002-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.test.context.observation; + +import java.lang.reflect.Method; + +import io.micrometer.observation.ObservationRegistry; +import io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.platform.launcher.TestExecutionListener; + +import org.springframework.context.ApplicationContext; +import org.springframework.core.Conventions; +import org.springframework.test.context.TestContext; +import org.springframework.test.context.support.AbstractTestExecutionListener; +import org.springframework.util.Assert; +import org.springframework.util.ReflectionUtils; + +/** + * {@code TestExecutionListener} which provides support for Micrometer's + * {@link ObservationRegistry}. + * + *

    This listener updates the {@link ObservationThreadLocalAccessor} with the + * {@code ObservationRegistry} obtained from the test's {@link ApplicationContext}, + * if present. + * + * @author Marcin Grzejszczak + * @author Sam Brannen + * @since 6.0.10 + */ +class MicrometerObservationRegistryTestExecutionListener extends AbstractTestExecutionListener { + + private static final Log logger = LogFactory.getLog(MicrometerObservationRegistryTestExecutionListener.class); + + private static final String OBSERVATION_THREAD_LOCAL_ACCESSOR_CLASS_NAME = + "io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor"; + + /** + * Attribute name for a {@link TestContext} attribute which contains the + * {@link ObservationRegistry} that was previously stored in the + * {@link ObservationThreadLocalAccessor}. + *

    After each test method, the previously stored {@code ObservationRegistry} + * will be restored. If tests run concurrently this might cause issues unless + * the {@code ObservationRegistry} is always the same (which should typically + * be the case). + */ + private static final String PREVIOUS_OBSERVATION_REGISTRY = Conventions.getQualifiedAttributeName( + MicrometerObservationRegistryTestExecutionListener.class, "previousObservationRegistry"); + + + static { + // Trigger eager resolution of Micrometer Observation types during static + // initialization of this class to ensure that this listener can be properly + // skipped when SpringFactoriesLoader attempts to load it, if micrometer-observation + // is not in the classpath or if the version of ObservationThreadLocalAccessor + // present does not include the getObservationRegistry() method. + String errorMessage = + "MicrometerObservationRegistryTestExecutionListener requires micrometer-observation 1.10.8 or higher"; + Class clazz; + try { + clazz = Class.forName(OBSERVATION_THREAD_LOCAL_ACCESSOR_CLASS_NAME, true, + TestExecutionListener.class.getClassLoader()); + } + catch (Throwable ex) { + throw new IllegalStateException(errorMessage, ex); + } + + Method method = ReflectionUtils.findMethod(clazz, "getObservationRegistry"); + Assert.state(method != null, errorMessage); + } + + + /** + * Returns {@code 2500}. + */ + @Override + public final int getOrder() { + return 2500; + } + + /** + * If the test's {@link ApplicationContext} contains an {@link ObservationRegistry} + * bean, this method retrieves the {@code ObservationRegistry} currently stored + * in {@link ObservationThreadLocalAccessor}, saves a reference to the original + * registry as a {@link TestContext} attribute (to be restored in + * {@link #afterTestMethod(TestContext)}), and sets the registry from the test's + * {@code ApplicationContext} in {@link ObservationThreadLocalAccessor}. + * @param testContext the test context for the test; never {@code null} + * @see #afterTestMethod(TestContext) + */ + @Override + public void beforeTestMethod(TestContext testContext) { + testContext.getApplicationContext().getBeanProvider(ObservationRegistry.class) + .ifAvailable(registry -> { + if (logger.isDebugEnabled()) { + logger.debug(""" + Registering ObservationRegistry from ApplicationContext in \ + ObservationThreadLocalAccessor for test class \ + """ + testContext.getTestClass().getName()); + } + ObservationThreadLocalAccessor accessor = ObservationThreadLocalAccessor.getInstance(); + testContext.setAttribute(PREVIOUS_OBSERVATION_REGISTRY, accessor.getObservationRegistry()); + accessor.setObservationRegistry(registry); + }); + } + + /** + * Retrieves the original {@link ObservationRegistry} that was saved in + * {@link #beforeTestMethod(TestContext)} and sets it in + * {@link ObservationThreadLocalAccessor}. + * @param testContext the test context for the test; never {@code null} + * @see #beforeTestMethod(TestContext) + */ + @Override + public void afterTestMethod(TestContext testContext) { + ObservationRegistry previousObservationRegistry = + (ObservationRegistry) testContext.removeAttribute(PREVIOUS_OBSERVATION_REGISTRY); + if (previousObservationRegistry != null) { + if (logger.isDebugEnabled()) { + logger.debug("Restoring ObservationRegistry in ObservationThreadLocalAccessor for test class " + + testContext.getTestClass().getName()); + } + ObservationThreadLocalAccessor.getInstance().setObservationRegistry(previousObservationRegistry); + } + } + +} diff --git a/spring-test/src/main/java/org/springframework/test/context/observation/MicrometerObservationThreadLocalTestExecutionListener.java b/spring-test/src/main/java/org/springframework/test/context/observation/MicrometerObservationThreadLocalTestExecutionListener.java deleted file mode 100644 index 63aa3b6b3176..000000000000 --- a/spring-test/src/main/java/org/springframework/test/context/observation/MicrometerObservationThreadLocalTestExecutionListener.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2002-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.test.context.observation; - -import io.micrometer.observation.ObservationRegistry; -import io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor; - -import org.springframework.context.ApplicationContext; -import org.springframework.core.Conventions; -import org.springframework.test.context.TestContext; -import org.springframework.test.context.TestExecutionListener; -import org.springframework.test.context.support.AbstractTestExecutionListener; - -/** - * {@code ObservationThreadLocalTestExecutionListener} is an implementation of the {@link TestExecutionListener} - * SPI that updates the {@link ObservationThreadLocalAccessor} with the {@link ObservationRegistry} - * taken from the {@link ApplicationContext} present in the {@link TestContext}. - * - *

    This implementation is not thread-safe. - * - * @author Marcin Grzejszczak - * @since 6.1 - */ -public class MicrometerObservationThreadLocalTestExecutionListener extends AbstractTestExecutionListener { - - /** - * Attribute name for a {@link TestContext} attribute which contains the previously - * set {@link ObservationRegistry} on the {@link ObservationThreadLocalAccessor}. - *

    After all tests from the current test class have completed, the previously stored {@link ObservationRegistry} - * will be restored. If tests are ran concurrently this might cause issues - * unless the {@link ObservationRegistry} is always the same (which should be the case most frequently). - */ - private static final String PREVIOUS_OBSERVATION_REGISTRY = Conventions.getQualifiedAttributeName( - MicrometerObservationThreadLocalTestExecutionListener.class, "previousObservationRegistry"); - - /** - * Retrieves the current {@link ObservationRegistry} stored - * on {@link ObservationThreadLocalAccessor} instance and stores it - * in the {@link TestContext} attributes and overrides it with - * one stored in {@link ApplicationContext} associated with - * the {@link TestContext}. - * @param testContext the test context for the test; never {@code null} - */ - @Override - public void beforeTestMethod(TestContext testContext) { - testContext.setAttribute(PREVIOUS_OBSERVATION_REGISTRY, - ObservationThreadLocalAccessor.getInstance().getObservationRegistry()); - testContext.getApplicationContext() - .getBeanProvider(ObservationRegistry.class) - .ifAvailable(observationRegistry -> - ObservationThreadLocalAccessor.getInstance() - .setObservationRegistry(observationRegistry)); - } - - /** - * Retrieves the previously stored {@link ObservationRegistry} and sets it back - * on the {@link ObservationThreadLocalAccessor} instance. - * @param testContext the test context for the test; never {@code null} - */ - @Override - public void afterTestMethod(TestContext testContext) { - ObservationRegistry previousObservationRegistry = - (ObservationRegistry) testContext.getAttribute(PREVIOUS_OBSERVATION_REGISTRY); - if (previousObservationRegistry != null) { - ObservationThreadLocalAccessor.getInstance() - .setObservationRegistry(previousObservationRegistry); - } - } - - - /** - * Returns {@code 3500}. - */ - @Override - public final int getOrder() { - return 3500; - } -} diff --git a/spring-test/src/main/resources/META-INF/spring.factories b/spring-test/src/main/resources/META-INF/spring.factories index 4bb2ddbef728..2b9e4e3c116f 100644 --- a/spring-test/src/main/resources/META-INF/spring.factories +++ b/spring-test/src/main/resources/META-INF/spring.factories @@ -5,11 +5,11 @@ org.springframework.test.context.TestExecutionListener = \ org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener,\ org.springframework.test.context.event.ApplicationEventsTestExecutionListener,\ org.springframework.test.context.support.DependencyInjectionTestExecutionListener,\ + org.springframework.test.context.observation.MicrometerObservationRegistryTestExecutionListener,\ org.springframework.test.context.support.DirtiesContextTestExecutionListener,\ org.springframework.test.context.transaction.TransactionalTestExecutionListener,\ org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener,\ - org.springframework.test.context.event.EventPublishingTestExecutionListener,\ - org.springframework.test.context.observation.MicrometerObservationThreadLocalTestExecutionListener + org.springframework.test.context.event.EventPublishingTestExecutionListener # Default ContextCustomizerFactory implementations for the Spring TestContext Framework # diff --git a/spring-test/src/test/java/org/springframework/test/context/TestExecutionListenersTests.java b/spring-test/src/test/java/org/springframework/test/context/TestExecutionListenersTests.java index e83025b2281c..a1e634c31807 100644 --- a/spring-test/src/test/java/org/springframework/test/context/TestExecutionListenersTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/TestExecutionListenersTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,13 +28,13 @@ import org.springframework.test.context.event.ApplicationEventsTestExecutionListener; import org.springframework.test.context.event.EventPublishingTestExecutionListener; import org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener; -import org.springframework.test.context.observation.MicrometerObservationThreadLocalTestExecutionListener; import org.springframework.test.context.support.AbstractTestExecutionListener; import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; import org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener; import org.springframework.test.context.support.DirtiesContextTestExecutionListener; import org.springframework.test.context.transaction.TransactionalTestExecutionListener; import org.springframework.test.context.web.ServletTestExecutionListener; +import org.springframework.util.ClassUtils; import static java.util.Arrays.asList; import static java.util.stream.Collectors.toList; @@ -57,14 +57,17 @@ */ class TestExecutionListenersTests { + private static final Class micrometerListenerClass = + ClassUtils.resolveClassName("org.springframework.test.context.observation.MicrometerObservationRegistryTestExecutionListener", null); + @Test void defaultListeners() { List> expected = asList(ServletTestExecutionListener.class,// DirtiesContextBeforeModesTestExecutionListener.class,// ApplicationEventsTestExecutionListener.class,// DependencyInjectionTestExecutionListener.class,// + micrometerListenerClass,// DirtiesContextTestExecutionListener.class,// - MicrometerObservationThreadLocalTestExecutionListener.class,// TransactionalTestExecutionListener.class,// SqlScriptsTestExecutionListener.class,// EventPublishingTestExecutionListener.class @@ -82,8 +85,8 @@ void defaultListenersMergedWithCustomListenerPrepended() { DirtiesContextBeforeModesTestExecutionListener.class,// ApplicationEventsTestExecutionListener.class,// DependencyInjectionTestExecutionListener.class,// + micrometerListenerClass,// DirtiesContextTestExecutionListener.class,// - MicrometerObservationThreadLocalTestExecutionListener.class,// TransactionalTestExecutionListener.class,// SqlScriptsTestExecutionListener.class,// EventPublishingTestExecutionListener.class @@ -100,8 +103,8 @@ void defaultListenersMergedWithCustomListenerAppended() { DirtiesContextBeforeModesTestExecutionListener.class,// ApplicationEventsTestExecutionListener.class,// DependencyInjectionTestExecutionListener.class,// + micrometerListenerClass,// DirtiesContextTestExecutionListener.class,// - MicrometerObservationThreadLocalTestExecutionListener.class,// TransactionalTestExecutionListener.class, SqlScriptsTestExecutionListener.class,// EventPublishingTestExecutionListener.class,// @@ -120,8 +123,8 @@ void defaultListenersMergedWithCustomListenerInserted() { ApplicationEventsTestExecutionListener.class,// DependencyInjectionTestExecutionListener.class,// BarTestExecutionListener.class,// + micrometerListenerClass,// DirtiesContextTestExecutionListener.class,// - MicrometerObservationThreadLocalTestExecutionListener.class,// TransactionalTestExecutionListener.class,// SqlScriptsTestExecutionListener.class,// EventPublishingTestExecutionListener.class @@ -366,9 +369,9 @@ static class BarTestExecutionListener extends AbstractTestExecutionListener { @Override public int getOrder() { - // 2500 is between DependencyInjectionTestExecutionListener (2000) and - // DirtiesContextTestExecutionListener (3000) - return 2500; + // 2250 is between DependencyInjectionTestExecutionListener (2000) and + // MicrometerObservationRegistryTestExecutionListener (2500) + return 2250; } } diff --git a/spring-test/src/test/java/org/springframework/test/context/observation/MicrometerObservationRegistryTestExecutionListenerTests.java b/spring-test/src/test/java/org/springframework/test/context/observation/MicrometerObservationRegistryTestExecutionListenerTests.java new file mode 100644 index 000000000000..46ab3cf5dec3 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/observation/MicrometerObservationRegistryTestExecutionListenerTests.java @@ -0,0 +1,107 @@ +/* + * Copyright 2002-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.test.context.observation; + +import java.util.HashMap; +import java.util.Map; + +import io.micrometer.observation.ObservationRegistry; +import io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import org.springframework.context.support.StaticApplicationContext; +import org.springframework.test.context.TestContext; +import org.springframework.test.context.TestExecutionListener; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.willAnswer; +import static org.mockito.Mockito.mock; + +/** + * Unit tests for {@link MicrometerObservationRegistryTestExecutionListener}. + * + * @author Marcin Grzejszczak + * @author Sam Brannen + * @since 6.0.10 + */ +class MicrometerObservationRegistryTestExecutionListenerTests { + + private final ObservationRegistry originalObservationRegistry = globalObservationRegistry(); + + private final TestContext testContext = mock(); + + private final StaticApplicationContext applicationContext = new StaticApplicationContext(); + + private final Map attributes = new HashMap<>(); + + private final TestExecutionListener listener = new MicrometerObservationRegistryTestExecutionListener(); + + + @BeforeEach + @SuppressWarnings({ "unchecked", "rawtypes" }) // for raw Class testClass + void configureTestContextMock() { + willAnswer(invocation -> attributes.put(invocation.getArgument(0), invocation.getArgument(1))) + .given(testContext).setAttribute(anyString(), any()); + given(testContext.removeAttribute(anyString())) + .willAnswer(invocation -> attributes.get(invocation.getArgument(0, String.class))); + given(testContext.getApplicationContext()).willReturn(applicationContext); + Class testClass = getClass(); + given(testContext.getTestClass()).willReturn(testClass); + } + + @Test + void observationRegistryIsNotOverridden() throws Exception { + assertGlobalObservationRegistryIsSameAsOriginal(); + + listener.beforeTestMethod(testContext); + assertGlobalObservationRegistryIsSameAsOriginal(); + + listener.afterTestMethod(testContext); + assertGlobalObservationRegistryIsSameAsOriginal(); + } + + @Test + void observationRegistryIsOverriddenByBeanFromApplicationContext() throws Exception { + assertGlobalObservationRegistryIsSameAsOriginal(); + + ObservationRegistry testObservationRegistry = ObservationRegistry.create(); + applicationContext.getDefaultListableBeanFactory().registerSingleton("observationRegistry", testObservationRegistry); + + listener.beforeTestMethod(testContext); + ObservationRegistry globalObservationRegistry = globalObservationRegistry(); + assertThat(globalObservationRegistry) + .as("The global ObservationRegistry should have been replaced with the one from the application context") + .isNotSameAs(originalObservationRegistry) + .isSameAs(testObservationRegistry); + + listener.afterTestMethod(testContext); + assertGlobalObservationRegistryIsSameAsOriginal(); + } + + private void assertGlobalObservationRegistryIsSameAsOriginal() { + assertThat(globalObservationRegistry()).isSameAs(originalObservationRegistry); + } + + private static ObservationRegistry globalObservationRegistry() { + return ObservationThreadLocalAccessor.getInstance().getObservationRegistry(); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/observation/MicrometerObservationThreadLocalTestExecutionListenerTests.java b/spring-test/src/test/java/org/springframework/test/context/observation/MicrometerObservationThreadLocalTestExecutionListenerTests.java deleted file mode 100644 index 4fa993a0fc1a..000000000000 --- a/spring-test/src/test/java/org/springframework/test/context/observation/MicrometerObservationThreadLocalTestExecutionListenerTests.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2002-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.test.context.observation; - -import java.util.HashMap; -import java.util.Map; - -import io.micrometer.observation.ObservationRegistry; -import io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import org.springframework.context.support.StaticApplicationContext; -import org.springframework.test.context.TestContext; - -import static org.assertj.core.api.BDDAssertions.then; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.willAnswer; -import static org.mockito.Mockito.mock; - -class MicrometerObservationThreadLocalTestExecutionListenerTests { - - ObservationRegistry originalObservationRegistry = ObservationThreadLocalAccessor.getInstance().getObservationRegistry(); - - TestContext testContext = mock(); - - StaticApplicationContext applicationContext = new StaticApplicationContext(); - - Map attributes = new HashMap<>(); - - MicrometerObservationThreadLocalTestExecutionListener listener = new MicrometerObservationThreadLocalTestExecutionListener(); - - @BeforeEach - void setup() { - willAnswer(invocation -> attributes.put(invocation.getArgument(0), invocation.getArgument(1))).given(testContext).setAttribute(anyString(), any()); - given(testContext.getAttribute(anyString())).willAnswer(invocation -> attributes.get(invocation.getArgument(0, String.class))); - given(testContext.getApplicationContext()).willReturn(applicationContext); - } - - @Test - void observationRegistryShouldNotBeOverridden() throws Exception { - listener.beforeTestMethod(testContext); - thenObservationRegistryOnOTLAIsSameAsOriginal(); - listener.afterTestMethod(testContext); - thenObservationRegistryOnOTLAIsSameAsOriginal(); - } - - @Test - void observationRegistryOverriddenByBeanFromTestContext() throws Exception { - ObservationRegistry newObservationRegistry = ObservationRegistry.create(); - applicationContext.getDefaultListableBeanFactory().registerSingleton("observationRegistry", newObservationRegistry); - - listener.beforeTestMethod(testContext); - ObservationRegistry otlaObservationRegistry = ObservationThreadLocalAccessor.getInstance().getObservationRegistry(); - then(otlaObservationRegistry) - .as("During the test we want the original ObservationRegistry to be replaced with the one present in this application context") - .isNotSameAs(originalObservationRegistry) - .isSameAs(newObservationRegistry); - - listener.afterTestMethod(testContext); - thenObservationRegistryOnOTLAIsSameAsOriginal(); - } - - private void thenObservationRegistryOnOTLAIsSameAsOriginal() { - then(ObservationThreadLocalAccessor.getInstance().getObservationRegistry()).isSameAs(originalObservationRegistry); - } - -} diff --git a/spring-test/src/test/resources/log4j2-test.xml b/spring-test/src/test/resources/log4j2-test.xml index 88cf6a3b9aa3..15645c85ebf1 100644 --- a/spring-test/src/test/resources/log4j2-test.xml +++ b/spring-test/src/test/resources/log4j2-test.xml @@ -18,6 +18,7 @@ +