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
This commit is contained in:
parent
c261ca3102
commit
6f79c7e70f
|
@ -27,9 +27,6 @@ creating unnecessary contexts.
|
||||||
====
|
====
|
||||||
|
|
||||||
Each annotation also defines Mockito-specific attributes to fine-tune the mocking details.
|
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`
|
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].
|
xref:testing/testcontext-framework/bean-overriding.adoc#testcontext-bean-overriding-custom[strategy for test bean overriding].
|
||||||
|
|
|
@ -10,7 +10,6 @@ by default, exactly in the following order:
|
||||||
annotation for "`before`" modes.
|
annotation for "`before`" modes.
|
||||||
* `ApplicationEventsTestExecutionListener`: Provides support for
|
* `ApplicationEventsTestExecutionListener`: Provides support for
|
||||||
xref:testing/testcontext-framework/application-events.adoc[`ApplicationEvents`].
|
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
|
* `DependencyInjectionTestExecutionListener`: Provides dependency injection for the test
|
||||||
instance.
|
instance.
|
||||||
* `MicrometerObservationRegistryTestExecutionListener`: Provides support for
|
* `MicrometerObservationRegistryTestExecutionListener`: Provides support for
|
||||||
|
|
|
@ -66,8 +66,6 @@ package org.springframework.test.context;
|
||||||
* DirtiesContextBeforeModesTestExecutionListener}</li>
|
* DirtiesContextBeforeModesTestExecutionListener}</li>
|
||||||
* <li>{@link org.springframework.test.context.event.ApplicationEventsTestExecutionListener
|
* <li>{@link org.springframework.test.context.event.ApplicationEventsTestExecutionListener
|
||||||
* ApplicationEventsTestExecutionListener}</li>
|
* ApplicationEventsTestExecutionListener}</li>
|
||||||
* <li>{@link org.springframework.test.context.bean.override.mockito.MockitoTestExecutionListener
|
|
||||||
* MockitoTestExecutionListener}</li>
|
|
||||||
* <li>{@link org.springframework.test.context.support.DependencyInjectionTestExecutionListener
|
* <li>{@link org.springframework.test.context.support.DependencyInjectionTestExecutionListener
|
||||||
* DependencyInjectionTestExecutionListener}</li>
|
* DependencyInjectionTestExecutionListener}</li>
|
||||||
* <li>{@link org.springframework.test.context.observation.MicrometerObservationRegistryTestExecutionListener
|
* <li>{@link org.springframework.test.context.observation.MicrometerObservationRegistryTestExecutionListener
|
||||||
|
|
|
@ -82,7 +82,6 @@ public @interface TestExecutionListeners {
|
||||||
* @see org.springframework.test.context.web.ServletTestExecutionListener
|
* @see org.springframework.test.context.web.ServletTestExecutionListener
|
||||||
* @see org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener
|
* @see org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener
|
||||||
* @see org.springframework.test.context.event.ApplicationEventsTestExecutionListener
|
* @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.DependencyInjectionTestExecutionListener
|
||||||
* @see org.springframework.test.context.support.DirtiesContextTestExecutionListener
|
* @see org.springframework.test.context.support.DirtiesContextTestExecutionListener
|
||||||
* @see org.springframework.test.context.support.CommonCachesTestExecutionListener
|
* @see org.springframework.test.context.support.CommonCachesTestExecutionListener
|
||||||
|
|
|
@ -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 SPRING_MOCKITO_PACKAGE = "org.springframework.test.context.bean.override.mockito";
|
||||||
|
|
||||||
private static final String ORG_MOCKITO_PACKAGE = "org.mockito";
|
|
||||||
|
|
||||||
private static final Predicate<MergedAnnotation<?>> isMockitoAnnotation = mergedAnnotation -> {
|
private static final Predicate<MergedAnnotation<?>> isMockitoAnnotation = mergedAnnotation -> {
|
||||||
String packageName = mergedAnnotation.getType().getPackageName();
|
String packageName = mergedAnnotation.getType().getPackageName();
|
||||||
return (packageName.startsWith(SPRING_MOCKITO_PACKAGE) ||
|
return packageName.startsWith(SPRING_MOCKITO_PACKAGE);
|
||||||
packageName.startsWith(ORG_MOCKITO_PACKAGE));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if the test class for the supplied {@linkplain TestContext
|
* Determine if the test class for the supplied {@linkplain TestContext
|
||||||
* test context} uses {@code org.mockito} annotations or any of the annotations
|
* test context} uses any of the annotations in this package (such as
|
||||||
* in this package (such as {@link MockitoBeanSettings @MockitoBeanSettings}).
|
* {@link MockitoBean @MockitoBean}).
|
||||||
*/
|
*/
|
||||||
static boolean hasMockitoAnnotations(TestContext testContext) {
|
static boolean hasMockitoAnnotations(TestContext testContext) {
|
||||||
return hasMockitoAnnotations(testContext.getTestClass());
|
return hasMockitoAnnotations(testContext.getTestClass());
|
||||||
|
|
|
@ -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();
|
|
||||||
|
|
||||||
}
|
|
|
@ -40,7 +40,6 @@ import org.springframework.test.context.TestContext;
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Sam Brannen
|
* @author Sam Brannen
|
||||||
* @since 6.2
|
* @since 6.2
|
||||||
* @see MockitoTestExecutionListener
|
|
||||||
* @see MockitoBean @MockitoBean
|
* @see MockitoBean @MockitoBean
|
||||||
* @see MockitoSpyBean @MockitoSpyBean
|
* @see MockitoSpyBean @MockitoSpyBean
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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.
|
|
||||||
*
|
|
||||||
* <p>The {@link MockitoSession#setStrictness(Strictness) strictness} of the
|
|
||||||
* session defaults to {@link Strictness#STRICT_STUBS}. Use
|
|
||||||
* {@code @MockitoBeanSettings} to specify a different strictness.
|
|
||||||
*
|
|
||||||
* <p>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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -4,7 +4,6 @@ org.springframework.test.context.TestExecutionListener = \
|
||||||
org.springframework.test.context.web.ServletTestExecutionListener,\
|
org.springframework.test.context.web.ServletTestExecutionListener,\
|
||||||
org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener,\
|
org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener,\
|
||||||
org.springframework.test.context.event.ApplicationEventsTestExecutionListener,\
|
org.springframework.test.context.event.ApplicationEventsTestExecutionListener,\
|
||||||
org.springframework.test.context.bean.override.mockito.MockitoTestExecutionListener,\
|
|
||||||
org.springframework.test.context.support.DependencyInjectionTestExecutionListener,\
|
org.springframework.test.context.support.DependencyInjectionTestExecutionListener,\
|
||||||
org.springframework.test.context.observation.MicrometerObservationRegistryTestExecutionListener,\
|
org.springframework.test.context.observation.MicrometerObservationRegistryTestExecutionListener,\
|
||||||
org.springframework.test.context.support.DirtiesContextTestExecutionListener,\
|
org.springframework.test.context.support.DirtiesContextTestExecutionListener,\
|
||||||
|
|
|
@ -27,7 +27,6 @@ import org.springframework.core.annotation.AliasFor;
|
||||||
import org.springframework.core.annotation.AnnotationConfigurationException;
|
import org.springframework.core.annotation.AnnotationConfigurationException;
|
||||||
import org.springframework.test.context.bean.override.BeanOverrideTestExecutionListener;
|
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.MockitoResetTestExecutionListener;
|
||||||
import org.springframework.test.context.bean.override.mockito.MockitoTestExecutionListener;
|
|
||||||
import org.springframework.test.context.event.ApplicationEventsTestExecutionListener;
|
import org.springframework.test.context.event.ApplicationEventsTestExecutionListener;
|
||||||
import org.springframework.test.context.event.EventPublishingTestExecutionListener;
|
import org.springframework.test.context.event.EventPublishingTestExecutionListener;
|
||||||
import org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener;
|
import org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener;
|
||||||
|
@ -69,7 +68,6 @@ class TestExecutionListenersTests {
|
||||||
List<Class<?>> expected = asList(ServletTestExecutionListener.class,//
|
List<Class<?>> expected = asList(ServletTestExecutionListener.class,//
|
||||||
DirtiesContextBeforeModesTestExecutionListener.class,//
|
DirtiesContextBeforeModesTestExecutionListener.class,//
|
||||||
ApplicationEventsTestExecutionListener.class,//
|
ApplicationEventsTestExecutionListener.class,//
|
||||||
MockitoTestExecutionListener.class,//
|
|
||||||
DependencyInjectionTestExecutionListener.class,//
|
DependencyInjectionTestExecutionListener.class,//
|
||||||
micrometerListenerClass,//
|
micrometerListenerClass,//
|
||||||
DirtiesContextTestExecutionListener.class,//
|
DirtiesContextTestExecutionListener.class,//
|
||||||
|
@ -92,7 +90,6 @@ class TestExecutionListenersTests {
|
||||||
ServletTestExecutionListener.class,//
|
ServletTestExecutionListener.class,//
|
||||||
DirtiesContextBeforeModesTestExecutionListener.class,//
|
DirtiesContextBeforeModesTestExecutionListener.class,//
|
||||||
ApplicationEventsTestExecutionListener.class,//
|
ApplicationEventsTestExecutionListener.class,//
|
||||||
MockitoTestExecutionListener.class,//
|
|
||||||
DependencyInjectionTestExecutionListener.class,//
|
DependencyInjectionTestExecutionListener.class,//
|
||||||
micrometerListenerClass,//
|
micrometerListenerClass,//
|
||||||
DirtiesContextTestExecutionListener.class,//
|
DirtiesContextTestExecutionListener.class,//
|
||||||
|
@ -114,7 +111,6 @@ class TestExecutionListenersTests {
|
||||||
List<Class<?>> expected = asList(ServletTestExecutionListener.class,//
|
List<Class<?>> expected = asList(ServletTestExecutionListener.class,//
|
||||||
DirtiesContextBeforeModesTestExecutionListener.class,//
|
DirtiesContextBeforeModesTestExecutionListener.class,//
|
||||||
ApplicationEventsTestExecutionListener.class,//
|
ApplicationEventsTestExecutionListener.class,//
|
||||||
MockitoTestExecutionListener.class,//
|
|
||||||
DependencyInjectionTestExecutionListener.class,//
|
DependencyInjectionTestExecutionListener.class,//
|
||||||
micrometerListenerClass,//
|
micrometerListenerClass,//
|
||||||
DirtiesContextTestExecutionListener.class,//
|
DirtiesContextTestExecutionListener.class,//
|
||||||
|
@ -137,7 +133,6 @@ class TestExecutionListenersTests {
|
||||||
List<Class<?>> expected = asList(ServletTestExecutionListener.class,//
|
List<Class<?>> expected = asList(ServletTestExecutionListener.class,//
|
||||||
DirtiesContextBeforeModesTestExecutionListener.class,//
|
DirtiesContextBeforeModesTestExecutionListener.class,//
|
||||||
ApplicationEventsTestExecutionListener.class,//
|
ApplicationEventsTestExecutionListener.class,//
|
||||||
MockitoTestExecutionListener.class,//
|
|
||||||
DependencyInjectionTestExecutionListener.class,//
|
DependencyInjectionTestExecutionListener.class,//
|
||||||
BarTestExecutionListener.class,//
|
BarTestExecutionListener.class,//
|
||||||
micrometerListenerClass,//
|
micrometerListenerClass,//
|
||||||
|
|
|
@ -30,9 +30,8 @@ import static org.mockito.BDDMockito.then;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verifies proper handling of the {@link org.mockito.MockitoSession MockitoSession}
|
* Verifies proper reset of mocks when a {@link MockitoBean @MockitoBean} field
|
||||||
* when a {@link MockitoBean @MockitoBean} field is declared in the enclosing class of
|
* is declared in the enclosing class of a {@link Nested @Nested} test class.
|
||||||
* a {@link Nested @Nested} test class.
|
|
||||||
*
|
*
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
* @author Sam Brannen
|
* @author Sam Brannen
|
||||||
|
|
|
@ -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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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<Arguments> 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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue