From 6f79c7e70f554669d4ad1379b9bfe2dd84512743 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Basl=C3=A9?= Date: Tue, 15 Oct 2024 18:29:36 +0200 Subject: [PATCH] Remove support for Mockito annotations and `MockitoSession` This change remove the support for Mockito annotations, `MockitoSession` and opening/closing of mocks that was inherited from Boot's `@MockBean` support, as well as the switch to `MockitoSession` made in 1c893e6. Attempting to take responsability for things Mockito's own JUnit Jupiter extension does better is not ideal, and we found it leads to several corner cases which make `SpringExtension` and `MockitoExtension` incompatible in the current approach. Instead, this change refocuses our Mockito bean overriding support exclusively on aspects specific to the Framework. `MockitoExtension` will thus be usable in conjunction with `SpringExtension` if one needs to use `@Captor`/`@InitMocks`/`@Mock`/`@Spy` or other Mockito utilities. See gh-33318 Closes gh-33692 --- .../annotation-mockitobean.adoc | 3 - .../testcontext-framework/tel-config.adoc | 1 - .../test/context/TestExecutionListener.java | 2 - .../test/context/TestExecutionListeners.java | 1 - .../AbstractMockitoTestExecutionListener.java | 9 +- .../override/mockito/MockitoBeanSettings.java | 47 ------ .../MockitoResetTestExecutionListener.java | 1 - .../mockito/MockitoTestExecutionListener.java | 102 ------------- .../main/resources/META-INF/spring.factories | 1 - .../context/TestExecutionListenersTests.java | 5 - .../mockito/MockitoBeanNestedTests.java | 5 +- ...oBeanSettingsInheritedStrictnessTests.java | 63 -------- ...toBeanSettingsLenientIntegrationTests.java | 56 ------- ...itoBeanSettingsStrictIntegrationTests.java | 141 ------------------ 14 files changed, 5 insertions(+), 432 deletions(-) delete mode 100644 spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoBeanSettings.java delete mode 100644 spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoTestExecutionListener.java delete mode 100644 spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanSettingsInheritedStrictnessTests.java delete mode 100644 spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanSettingsLenientIntegrationTests.java delete mode 100644 spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanSettingsStrictIntegrationTests.java diff --git a/framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-mockitobean.adoc b/framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-mockitobean.adoc index acea0e8dcf..8c87c43c77 100644 --- a/framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-mockitobean.adoc +++ b/framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-mockitobean.adoc @@ -27,9 +27,6 @@ creating unnecessary contexts. ==== Each annotation also defines Mockito-specific attributes to fine-tune the mocking details. -During the test class lifecycle, Mockito is set up via the `Mockito#mockitoSession()` -mechanism. Notably, it enables `STRICT_STUBS` mode by default. This can be changed on -individual test classes with the `@MockitoBeanSettings` annotation. By default, the `@MockitoBean` annotation uses the `REPLACE_OR_CREATE` xref:testing/testcontext-framework/bean-overriding.adoc#testcontext-bean-overriding-custom[strategy for test bean overriding]. 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 bb7f79e808..628edcc21d 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 @@ -10,7 +10,6 @@ by default, exactly in the following order: annotation for "`before`" modes. * `ApplicationEventsTestExecutionListener`: Provides support for xref:testing/testcontext-framework/application-events.adoc[`ApplicationEvents`]. -* `MockitoTestExecutionListener`: Initializes and closes mocks configured using `@MockitoBean` or `@MockitoSpyBean`. * `DependencyInjectionTestExecutionListener`: Provides dependency injection for the test instance. * `MicrometerObservationRegistryTestExecutionListener`: Provides support for 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 e5e85b8209..a2d81e84b2 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 @@ -66,8 +66,6 @@ package org.springframework.test.context; * DirtiesContextBeforeModesTestExecutionListener} *
  • {@link org.springframework.test.context.event.ApplicationEventsTestExecutionListener * ApplicationEventsTestExecutionListener}
  • - *
  • {@link org.springframework.test.context.bean.override.mockito.MockitoTestExecutionListener - * MockitoTestExecutionListener}
  • *
  • {@link org.springframework.test.context.support.DependencyInjectionTestExecutionListener * DependencyInjectionTestExecutionListener}
  • *
  • {@link org.springframework.test.context.observation.MicrometerObservationRegistryTestExecutionListener diff --git a/spring-test/src/main/java/org/springframework/test/context/TestExecutionListeners.java b/spring-test/src/main/java/org/springframework/test/context/TestExecutionListeners.java index b63720bb0e..2bb68cceb5 100644 --- a/spring-test/src/main/java/org/springframework/test/context/TestExecutionListeners.java +++ b/spring-test/src/main/java/org/springframework/test/context/TestExecutionListeners.java @@ -82,7 +82,6 @@ public @interface TestExecutionListeners { * @see org.springframework.test.context.web.ServletTestExecutionListener * @see org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener * @see org.springframework.test.context.event.ApplicationEventsTestExecutionListener - * @see org.springframework.test.context.bean.override.mockito.MockitoTestExecutionListener * @see org.springframework.test.context.support.DependencyInjectionTestExecutionListener * @see org.springframework.test.context.support.DirtiesContextTestExecutionListener * @see org.springframework.test.context.support.CommonCachesTestExecutionListener diff --git a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/AbstractMockitoTestExecutionListener.java b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/AbstractMockitoTestExecutionListener.java index c6f4dbf477..7ef700bfdc 100644 --- a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/AbstractMockitoTestExecutionListener.java +++ b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/AbstractMockitoTestExecutionListener.java @@ -42,19 +42,16 @@ abstract class AbstractMockitoTestExecutionListener extends AbstractTestExecutio private static final String SPRING_MOCKITO_PACKAGE = "org.springframework.test.context.bean.override.mockito"; - private static final String ORG_MOCKITO_PACKAGE = "org.mockito"; - private static final Predicate> isMockitoAnnotation = mergedAnnotation -> { String packageName = mergedAnnotation.getType().getPackageName(); - return (packageName.startsWith(SPRING_MOCKITO_PACKAGE) || - packageName.startsWith(ORG_MOCKITO_PACKAGE)); + return packageName.startsWith(SPRING_MOCKITO_PACKAGE); }; /** * Determine if the test class for the supplied {@linkplain TestContext - * test context} uses {@code org.mockito} annotations or any of the annotations - * in this package (such as {@link MockitoBeanSettings @MockitoBeanSettings}). + * test context} uses any of the annotations in this package (such as + * {@link MockitoBean @MockitoBean}). */ static boolean hasMockitoAnnotations(TestContext testContext) { return hasMockitoAnnotations(testContext.getTestClass()); diff --git a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoBeanSettings.java b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoBeanSettings.java deleted file mode 100644 index c375af2b65..0000000000 --- a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoBeanSettings.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2002-2024 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.bean.override.mockito; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.mockito.quality.Strictness; - -/** - * Configure a test class that uses {@link MockitoBean @MockitoBean} or - * {@link MockitoSpyBean @MockitoSpyBean} to set up Mockito with an explicit - * stubbing strictness mode. - * - * @author Simon Baslé - * @since 6.2 - * @see MockitoTestExecutionListener - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface MockitoBeanSettings { - - /** - * The stubbing strictness mode to apply for all Mockito mocks in the annotated - * test class. - */ - Strictness value(); - -} diff --git a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoResetTestExecutionListener.java b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoResetTestExecutionListener.java index 63f0d6329f..7f6b7225b9 100644 --- a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoResetTestExecutionListener.java +++ b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoResetTestExecutionListener.java @@ -40,7 +40,6 @@ import org.springframework.test.context.TestContext; * @author Phillip Webb * @author Sam Brannen * @since 6.2 - * @see MockitoTestExecutionListener * @see MockitoBean @MockitoBean * @see MockitoSpyBean @MockitoSpyBean */ diff --git a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoTestExecutionListener.java b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoTestExecutionListener.java deleted file mode 100644 index 8053f27146..0000000000 --- a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoTestExecutionListener.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2002-2024 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.bean.override.mockito; - -import org.mockito.Mockito; -import org.mockito.MockitoSession; -import org.mockito.quality.Strictness; - -import org.springframework.test.context.TestContext; -import org.springframework.test.context.TestContextAnnotationUtils; -import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; - -/** - * {@code TestExecutionListener} that manages a {@link MockitoSession} for each - * test class that uses {@link MockitoBean @MockitoBean}, - * {@link MockitoSpyBean @MockitoSpyBean}, - * {@link MockitoBeanSettings @MockitoBeanSettings}, or any annotations from the - * {@code org.mockito} package. - * - *

    The {@link MockitoSession#setStrictness(Strictness) strictness} of the - * session defaults to {@link Strictness#STRICT_STUBS}. Use - * {@code @MockitoBeanSettings} to specify a different strictness. - * - *

    Dependency injection for {@code @MockitoBean} and {@code @MockitoSpyBean} - * fields is handled by the - * {@link org.springframework.test.context.bean.override.BeanOverrideTestExecutionListener - * BeanOverrideTestExecutionListener}, and automatic reset support for - * {@code @MockitoBean} and {@code @MockitoSpyBean} is handled by the - * {@link MockitoResetTestExecutionListener}. - * - * @author Simon Baslé - * @author Sam Brannen - * @since 6.2 - * @see MockitoResetTestExecutionListener - * @see MockitoBean @MockitoBean - * @see MockitoSpyBean @MockitoSpyBean - */ -public class MockitoTestExecutionListener extends AbstractMockitoTestExecutionListener { - - private static final String MOCKITO_SESSION_ATTRIBUTE_NAME = - MockitoTestExecutionListener.class.getName() + ".mockitoSession"; - - - /** - * Executes before {@link DependencyInjectionTestExecutionListener}. - */ - @Override - public final int getOrder() { - return 1950; - } - - @Override - public void beforeTestMethod(TestContext testContext) { - if (mockitoPresent && hasMockitoAnnotations(testContext)) { - initMocks(testContext); - } - } - - @Override - public void afterTestMethod(TestContext testContext) { - if (mockitoPresent && hasMockitoAnnotations(testContext)) { - closeMocks(testContext); - } - } - - private static void initMocks(TestContext testContext) { - Class testClass = testContext.getTestClass(); - Object testInstance = testContext.getTestInstance(); - MockitoBeanSettings annotation = - TestContextAnnotationUtils.findMergedAnnotation(testClass, MockitoBeanSettings.class); - Strictness strictness = (annotation != null ? annotation.value() : Strictness.STRICT_STUBS); - testContext.setAttribute(MOCKITO_SESSION_ATTRIBUTE_NAME, initMockitoSession(testInstance, strictness)); - } - - private static MockitoSession initMockitoSession(Object testInstance, Strictness strictness) { - return Mockito.mockitoSession() - .initMocks(testInstance) - .strictness(strictness) - .startMocking(); - } - - private static void closeMocks(TestContext testContext) { - if (testContext.getAttribute(MOCKITO_SESSION_ATTRIBUTE_NAME) instanceof MockitoSession session) { - session.finishMocking(); - } - } - -} diff --git a/spring-test/src/main/resources/META-INF/spring.factories b/spring-test/src/main/resources/META-INF/spring.factories index ffae3b0b81..57c10c50bf 100644 --- a/spring-test/src/main/resources/META-INF/spring.factories +++ b/spring-test/src/main/resources/META-INF/spring.factories @@ -4,7 +4,6 @@ org.springframework.test.context.TestExecutionListener = \ org.springframework.test.context.web.ServletTestExecutionListener,\ org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener,\ org.springframework.test.context.event.ApplicationEventsTestExecutionListener,\ - org.springframework.test.context.bean.override.mockito.MockitoTestExecutionListener,\ org.springframework.test.context.support.DependencyInjectionTestExecutionListener,\ org.springframework.test.context.observation.MicrometerObservationRegistryTestExecutionListener,\ org.springframework.test.context.support.DirtiesContextTestExecutionListener,\ 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 ad36a45b28..ced6f3cba0 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 @@ -27,7 +27,6 @@ import org.springframework.core.annotation.AliasFor; import org.springframework.core.annotation.AnnotationConfigurationException; import org.springframework.test.context.bean.override.BeanOverrideTestExecutionListener; import org.springframework.test.context.bean.override.mockito.MockitoResetTestExecutionListener; -import org.springframework.test.context.bean.override.mockito.MockitoTestExecutionListener; import org.springframework.test.context.event.ApplicationEventsTestExecutionListener; import org.springframework.test.context.event.EventPublishingTestExecutionListener; import org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener; @@ -69,7 +68,6 @@ class TestExecutionListenersTests { List> expected = asList(ServletTestExecutionListener.class,// DirtiesContextBeforeModesTestExecutionListener.class,// ApplicationEventsTestExecutionListener.class,// - MockitoTestExecutionListener.class,// DependencyInjectionTestExecutionListener.class,// micrometerListenerClass,// DirtiesContextTestExecutionListener.class,// @@ -92,7 +90,6 @@ class TestExecutionListenersTests { ServletTestExecutionListener.class,// DirtiesContextBeforeModesTestExecutionListener.class,// ApplicationEventsTestExecutionListener.class,// - MockitoTestExecutionListener.class,// DependencyInjectionTestExecutionListener.class,// micrometerListenerClass,// DirtiesContextTestExecutionListener.class,// @@ -114,7 +111,6 @@ class TestExecutionListenersTests { List> expected = asList(ServletTestExecutionListener.class,// DirtiesContextBeforeModesTestExecutionListener.class,// ApplicationEventsTestExecutionListener.class,// - MockitoTestExecutionListener.class,// DependencyInjectionTestExecutionListener.class,// micrometerListenerClass,// DirtiesContextTestExecutionListener.class,// @@ -137,7 +133,6 @@ class TestExecutionListenersTests { List> expected = asList(ServletTestExecutionListener.class,// DirtiesContextBeforeModesTestExecutionListener.class,// ApplicationEventsTestExecutionListener.class,// - MockitoTestExecutionListener.class,// DependencyInjectionTestExecutionListener.class,// BarTestExecutionListener.class,// micrometerListenerClass,// diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanNestedTests.java index 6a02168eca..a42aaa5dab 100644 --- a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanNestedTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanNestedTests.java @@ -30,9 +30,8 @@ import static org.mockito.BDDMockito.then; import static org.mockito.Mockito.times; /** - * Verifies proper handling of the {@link org.mockito.MockitoSession MockitoSession} - * when a {@link MockitoBean @MockitoBean} field is declared in the enclosing class of - * a {@link Nested @Nested} test class. + * Verifies proper reset of mocks when a {@link MockitoBean @MockitoBean} field + * is declared in the enclosing class of a {@link Nested @Nested} test class. * * @author Andy Wilkinson * @author Sam Brannen diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanSettingsInheritedStrictnessTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanSettingsInheritedStrictnessTests.java deleted file mode 100644 index 752c01d908..0000000000 --- a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanSettingsInheritedStrictnessTests.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2002-2024 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.bean.override.mockito; - -import java.util.List; - -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.quality.Strictness; - -import org.springframework.test.context.TestExecutionListeners; -import org.springframework.test.context.junit.jupiter.SpringExtension; - -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.BDDMockito.when; -import static org.mockito.Mockito.mock; - -/** - * Tests which verify that strictness configured via - * {@link MockitoBeanSettings @MockitoBeanSettings} is inherited in - * {@link Nested @Nested} test classes. - * - * @author Sam Brannen - * @since 6.2 - */ -@ExtendWith(SpringExtension.class) -@TestExecutionListeners(MockitoTestExecutionListener.class) -@MockitoBeanSettings(Strictness.LENIENT) -class MockitoBeanSettingsInheritedStrictnessTests { - - // Should inherit Strictness.LENIENT. - @Nested - class NestedTests { - - @Test - @SuppressWarnings("rawtypes") - void unnecessaryStub() { - List list = mock(); - when(list.get(anyInt())).thenReturn("enigma"); - - // We intentionally do NOT perform any assertions against the mock, - // because we want to ensure that an UnnecessaryStubbingException is - // not thrown by Mockito. - // assertThat(list.get(1)).isEqualTo("enigma"); - } - } - -} diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanSettingsLenientIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanSettingsLenientIntegrationTests.java deleted file mode 100644 index 315e65fd2f..0000000000 --- a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanSettingsLenientIntegrationTests.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2002-2024 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.bean.override.mockito; - -import java.util.List; - -import org.junit.jupiter.api.Test; -import org.mockito.quality.Strictness; - -import org.springframework.context.annotation.Configuration; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; - -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.BDDMockito.when; -import static org.mockito.Mockito.mock; - -/** - * Integration tests for explicitly-defined {@link MockitoBeanSettings} with - * lenient stubbing. - * - * @author Simon Baslé - * @since 6.2 - */ -@SpringJUnitConfig -@DirtiesContext -@MockitoBeanSettings(Strictness.LENIENT) -class MockitoBeanSettingsLenientIntegrationTests { - - @Test - @SuppressWarnings("rawtypes") - void unusedStubbingNotReported() { - List list = mock(); - when(list.get(anyInt())).thenReturn(new Object()); - } - - @Configuration(proxyBeanMethods = false) - static class Config { - // no beans - } - -} diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanSettingsStrictIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanSettingsStrictIntegrationTests.java deleted file mode 100644 index d74685ccc0..0000000000 --- a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanSettingsStrictIntegrationTests.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright 2002-2024 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.bean.override.mockito; - -import java.util.List; - -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.FieldSource; -import org.junit.platform.testkit.engine.EngineTestKit; -import org.junit.platform.testkit.engine.Events; -import org.mockito.exceptions.misusing.UnnecessaryStubbingException; - -import org.springframework.context.annotation.Configuration; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; - -import static org.junit.jupiter.params.provider.Arguments.argumentSet; -import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; -import static org.junit.platform.testkit.engine.EventConditions.event; -import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; -import static org.junit.platform.testkit.engine.EventConditions.test; -import static org.junit.platform.testkit.engine.TestExecutionResultConditions.instanceOf; -import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.BDDMockito.when; -import static org.mockito.Mockito.mock; -import static org.mockito.quality.Strictness.LENIENT; -import static org.mockito.quality.Strictness.STRICT_STUBS; - -/** - * Integration tests ensuring unnecessary stubbing is reported in various - * cases where a strict style is chosen or assumed. - * - * @author Simon Baslé - * @author Sam Brannen - * @since 6.2 - */ -class MockitoBeanSettingsStrictIntegrationTests { - - @ParameterizedTest - @FieldSource("strictCases") - void unusedStubbingIsReported(Class testCase, int startedCount, int failureCount) { - Events events = EngineTestKit.engine("junit-jupiter") - .selectors(selectClass(testCase)) - .execute() - .testEvents() - .assertStatistics(stats -> stats.started(startedCount).failed(failureCount)); - - events.assertThatEvents().haveExactly(failureCount, - event(test("unnecessaryStub"), - finishedWithFailure( - instanceOf(UnnecessaryStubbingException.class), - message(msg -> msg.contains("Unnecessary stubbings detected."))))); - } - - static final List strictCases = List.of( - argumentSet("explicit strictness", ExplicitStrictness.class, 1, 1), - argumentSet("explicit strictness on enclosing class", ExplicitStrictnessEnclosingTestCase.class, 1, 1), - argumentSet("implicit strictness with @MockitoBean on field", ImplicitStrictnessWithMockitoBean.class, 1, 1), - // 3, 1 --> The tests in LenientStubbingNestedTestCase and InheritedLenientStubbingNestedTestCase - // should not result in an UnnecessaryStubbingException. - argumentSet("implicit strictness overridden and inherited in @Nested test classes", - ImplicitStrictnessWithMockitoBeanEnclosingTestCase.class, 3, 1) - ); - - abstract static class BaseCase { - - @Test - @SuppressWarnings("rawtypes") - void unnecessaryStub() { - List list = mock(); - when(list.get(anyInt())).thenReturn(new Object()); - } - } - - @SpringJUnitConfig(Config.class) - @DirtiesContext - @MockitoBeanSettings(STRICT_STUBS) - static class ExplicitStrictness extends BaseCase { - } - - @SpringJUnitConfig(Config.class) - @DirtiesContext - static class ImplicitStrictnessWithMockitoBean extends BaseCase { - - @MockitoBean - Runnable ignoredMock; - } - - @SpringJUnitConfig(Config.class) - @DirtiesContext - @MockitoBeanSettings(STRICT_STUBS) - static class ExplicitStrictnessEnclosingTestCase { - - @Nested - class NestedTestCase extends BaseCase { - } - } - - @SpringJUnitConfig(Config.class) - @DirtiesContext - static class ImplicitStrictnessWithMockitoBeanEnclosingTestCase extends BaseCase { - - @MockitoBean - Runnable ignoredMock; - - @Nested - // Overrides implicit STRICT_STUBS - @MockitoBeanSettings(LENIENT) - class LenientStubbingNestedTestCase extends BaseCase { - - @Nested - // Inherits LENIENT - class InheritedLenientStubbingNestedTestCase extends BaseCase { - } - } - } - - @Configuration(proxyBeanMethods = false) - static class Config { - // no beans - } - -}