Support @⁠MockitoBean at the type level on test classes

Prior to this commit, @⁠MockitoBean could only be declared on fields
within test classes, which prevented developers from being able to
easily reuse mock configuration across a test suite.

With this commit, @⁠MockitoBean is now supported at the type level on
test classes, their superclasses, and interfaces implemented by those
classes. @⁠MockitoBean is also supported on enclosing classes for
@⁠Nested test classes, their superclasses, and interfaces implemented
by those classes, while honoring @⁠NestedTestConfiguration semantics.

In addition, @⁠MockitoBean:

- has a new `types` attribute that can be used to declare the type or
  types to mock when @⁠MockitoBean is declared at the type level

- can be declared as a repeatable annotation at the type level

- can be declared as a meta-annotation on a custom composed annotation
  which can be reused across a test suite (see the @⁠SharedMocks
  example in the reference manual)

To support these new features, this commit also includes the following
changes.

- The `field` property in BeanOverrideHandler is now @⁠Nullable.

- BeanOverrideProcessor has a new `default` createHandlers() method
  which is invoked when a @⁠BeanOverride annotation is found at the
  type level.

- MockitoBeanOverrideProcessor implements the new createHandlers()
  method.

- The internal findHandlers() method in BeanOverrideHandler has been
  completely overhauled.

- The @⁠MockitoBean and @⁠MockitoSpyBean section of the reference
  manual has been completely overhauled.

Closes gh-33925
This commit is contained in:
Sam Brannen
2025-01-03 12:09:04 +02:00
parent 8b6523a35b
commit 9181cce65f
36 changed files with 1380 additions and 145 deletions

View File

@@ -30,4 +30,8 @@ public abstract class BeanOverrideTestUtils {
return BeanOverrideHandler.forTestClass(testClass);
}
public static List<BeanOverrideHandler> findAllHandlers(Class<?> testClass) {
return BeanOverrideHandler.findAllHandlers(testClass);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -67,6 +67,76 @@ class MockitoBeanOverrideHandlerTests {
assertThat(handler1).hasSameHashCodeAs(handler2);
}
@Test // gh-33925
void isEqualToWithSameInstanceFromClassLevel() {
MockitoBeanOverrideHandler handler1 = createHandler(ClassLevelStringMockByName1.class);
assertThat(handler1).isEqualTo(handler1);
assertThat(handler1).hasSameHashCodeAs(handler1);
MockitoBeanOverrideHandler handler2 = createHandler(ClassLevelStringMockByType1.class);
assertThat(handler2).isEqualTo(handler2);
assertThat(handler2).hasSameHashCodeAs(handler2);
}
@Test // gh-33925
void isEqualToWithSameByNameLookupMetadataFromClassLevel() {
MockitoBeanOverrideHandler handler1 = createHandler(ClassLevelStringMockByName1.class);
MockitoBeanOverrideHandler handler2 = createHandler(ClassLevelStringMockByName2.class);
assertThat(handler1).isEqualTo(handler2);
assertThat(handler2).isEqualTo(handler1);
assertThat(handler1).hasSameHashCodeAs(handler2);
}
@Test // gh-33925
void isNotEqualToWithDifferentByNameLookupMetadataFromClassLevel() {
MockitoBeanOverrideHandler handler1 = createHandler(ClassLevelStringMockByName1.class);
MockitoBeanOverrideHandler handler2 = createHandler(ClassLevelStringMockByName3.class);
assertThat(handler1).isNotEqualTo(handler2);
assertThat(handler2).isNotEqualTo(handler1);
assertThat(handler1).doesNotHaveSameHashCodeAs(handler2);
}
@Test // gh-33925
void isEqualToWithSameByTypeLookupMetadataFromClassLevel() {
MockitoBeanOverrideHandler handler1 = createHandler(ClassLevelStringMockByType1.class);
MockitoBeanOverrideHandler handler2 = createHandler(ClassLevelStringMockByType2.class);
assertThat(handler1).isEqualTo(handler2);
assertThat(handler2).isEqualTo(handler1);
assertThat(handler1).hasSameHashCodeAs(handler2);
}
@Test // gh-33925
void isNotEqualToWithDifferentByTypeLookupMetadataFromClassLevel() {
MockitoBeanOverrideHandler handler1 = createHandler(ClassLevelStringMockByType1.class);
MockitoBeanOverrideHandler handler2 = createHandler(ClassLevelStringMockByType3.class);
assertThat(handler1).isNotEqualTo(handler2);
assertThat(handler2).isNotEqualTo(handler1);
assertThat(handler1).doesNotHaveSameHashCodeAs(handler2);
}
@Test // gh-33925
void isEqualToWithSameByNameLookupMetadataFromFieldAndClassLevel() {
MockitoBeanOverrideHandler handler1 = createHandler(sampleField("service3"));
MockitoBeanOverrideHandler handler2 = createHandler(ClassLevelStringMockByName1.class);
assertThat(handler1).isEqualTo(handler2);
assertThat(handler2).isEqualTo(handler1);
assertThat(handler1).hasSameHashCodeAs(handler2);
}
/**
* Since the "field name as fallback qualifier" is not available for an annotated class,
* what would seem to be "equivalent" handlers are actually not considered "equal" when
* the the lookup is "by type".
*/
@Test // gh-33925
void isNotEqualToWithSameByTypeLookupMetadataFromFieldAndClassLevel() {
MockitoBeanOverrideHandler handler1 = createHandler(sampleField("service"));
MockitoBeanOverrideHandler handler2 = createHandler(ClassLevelStringMockByType1.class);
assertThat(handler1).isNotEqualTo(handler2);
assertThat(handler2).isNotEqualTo(handler1);
assertThat(handler1).doesNotHaveSameHashCodeAs(handler2);
}
@Test
void isNotEqualEqualToByTypeLookupWithSameMetadataButDifferentField() {
MockitoBeanOverrideHandler handler1 = createHandler(sampleField("service"));
@@ -122,6 +192,11 @@ class MockitoBeanOverrideHandlerTests {
return new MockitoBeanOverrideHandler(field, ResolvableType.forClass(field.getType()), annotation);
}
private MockitoBeanOverrideHandler createHandler(Class<?> clazz) {
MockitoBean annotation = AnnotatedElementUtils.getMergedAnnotation(clazz, MockitoBean.class);
return new MockitoBeanOverrideHandler(null, ResolvableType.forClass(annotation.types()[0]), annotation);
}
static class SampleOneMock {
@@ -159,4 +234,28 @@ class MockitoBeanOverrideHandlerTests {
private String service7;
}
@MockitoBean(name = "beanToMock", types = String.class)
static class ClassLevelStringMockByName1 {
}
@MockitoBean(name = "beanToMock", types = String.class)
static class ClassLevelStringMockByName2 {
}
@MockitoBean(name = "otherBeanToMock", types = String.class)
static class ClassLevelStringMockByName3 {
}
@MockitoBean(types = String.class)
static class ClassLevelStringMockByType1 {
}
@MockitoBean(types = String.class)
static class ClassLevelStringMockByType2 {
}
@MockitoBean(types = Integer.class)
static class ClassLevelStringMockByType3 {
}
}

View File

@@ -18,7 +18,9 @@ package org.springframework.test.context.bean.override.mockito;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.List;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.core.annotation.AnnotationUtils;
@@ -41,43 +43,155 @@ class MockitoBeanOverrideProcessorTests {
private final MockitoBeanOverrideProcessor processor = new MockitoBeanOverrideProcessor();
private final Field field = ReflectionUtils.findField(TestCase.class, "number");
@Nested
class CreateHandlerTests {
private final Field field = ReflectionUtils.findField(TestCase.class, "number");
@Test
void mockAnnotationCreatesMockitoBeanOverrideHandler() {
MockitoBean annotation = AnnotationUtils.synthesizeAnnotation(MockitoBean.class);
BeanOverrideHandler object = processor.createHandler(annotation, TestCase.class, field);
@Test
void mockAnnotationCreatesMockitoBeanOverrideHandler() {
MockitoBean annotation = AnnotationUtils.synthesizeAnnotation(MockitoBean.class);
BeanOverrideHandler object = processor.createHandler(annotation, TestCase.class, field);
assertThat(object).isExactlyInstanceOf(MockitoBeanOverrideHandler.class);
assertThat(object).isExactlyInstanceOf(MockitoBeanOverrideHandler.class);
}
@Test
void spyAnnotationCreatesMockitoSpyBeanOverrideHandler() {
MockitoSpyBean annotation = AnnotationUtils.synthesizeAnnotation(MockitoSpyBean.class);
BeanOverrideHandler object = processor.createHandler(annotation, TestCase.class, field);
assertThat(object).isExactlyInstanceOf(MockitoSpyBeanOverrideHandler.class);
}
@Test
void otherAnnotationThrows() {
Annotation annotation = field.getAnnotation(Nullable.class);
assertThatIllegalStateException()
.isThrownBy(() -> processor.createHandler(annotation, TestCase.class, field))
.withMessage("Invalid annotation passed to MockitoBeanOverrideProcessor: expected either " +
"@MockitoBean or @MockitoSpyBean on field %s.%s", field.getDeclaringClass().getName(),
field.getName());
}
@Test
void typesNotSupportedAtFieldLevel() {
Field field = ReflectionUtils.findField(TestCase.class, "typesNotSupported");
MockitoBean annotation = field.getAnnotation(MockitoBean.class);
assertThatIllegalStateException()
.isThrownBy(() -> processor.createHandler(annotation, TestCase.class, field))
.withMessage("The @MockitoBean 'types' attribute must be omitted when declared on a field");
}
static class TestCase {
@Nullable
@MockitoBean
@MockitoSpyBean
Integer number;
@MockitoBean(types = Integer.class)
String typesNotSupported;
}
@MockitoBean(name = "bogus", types = Integer.class)
static class NameNotSupportedTestCase {
}
}
@Test
void spyAnnotationCreatesMockitoSpyBeanOverrideHandler() {
MockitoSpyBean annotation = AnnotationUtils.synthesizeAnnotation(MockitoSpyBean.class);
BeanOverrideHandler object = processor.createHandler(annotation, TestCase.class, field);
@Nested
class CreateHandlersTests {
assertThat(object).isExactlyInstanceOf(MockitoSpyBeanOverrideHandler.class);
}
@Test
void missingTypes() {
Class<?> testClass = MissingTypesTestCase.class;
MockitoBean annotation = testClass.getAnnotation(MockitoBean.class);
@Test
void otherAnnotationThrows() {
Annotation annotation = field.getAnnotation(Nullable.class);
assertThatIllegalStateException()
.isThrownBy(() -> processor.createHandlers(annotation, testClass))
.withMessage("The @MockitoBean 'types' attribute must not be empty when declared on a class");
}
assertThatIllegalStateException()
.isThrownBy(() -> processor.createHandler(annotation, TestCase.class, field))
.withMessage("Invalid annotation passed to MockitoBeanOverrideProcessor: expected either " +
"@MockitoBean or @MockitoSpyBean on field %s.%s", field.getDeclaringClass().getName(),
field.getName());
}
@Test
void nameNotSupportedWithMultipleTypes() {
Class<?> testClass = NameNotSupportedWithMultipleTypesTestCase.class;
MockitoBean annotation = testClass.getAnnotation(MockitoBean.class);
assertThatIllegalStateException()
.isThrownBy(() -> processor.createHandlers(annotation, testClass))
.withMessage("The @MockitoBean 'name' attribute cannot be used when mocking multiple types");
}
@Test
void singleMockByType() {
Class<?> testClass = SingleMockByTypeTestCase.class;
MockitoBean annotation = testClass.getAnnotation(MockitoBean.class);
List<BeanOverrideHandler> handlers = processor.createHandlers(annotation, testClass);
assertThat(handlers).singleElement().isInstanceOfSatisfying(MockitoBeanOverrideHandler.class, handler -> {
assertThat(handler.getField()).isNull();
assertThat(handler.getBeanName()).isNull();
assertThat(handler.getBeanType().resolve()).isEqualTo(Integer.class);
});
}
@Test
void singleMockByName() {
Class<?> testClass = SingleMockByNameTestCase.class;
MockitoBean annotation = testClass.getAnnotation(MockitoBean.class);
List<BeanOverrideHandler> handlers = processor.createHandlers(annotation, testClass);
assertThat(handlers).singleElement().isInstanceOfSatisfying(MockitoBeanOverrideHandler.class, handler -> {
assertThat(handler.getField()).isNull();
assertThat(handler.getBeanName()).isEqualTo("enigma");
assertThat(handler.getBeanType().resolve()).isEqualTo(Integer.class);
});
}
@Test
void multipleMocks() {
Class<?> testClass = MultipleMocksTestCase.class;
MockitoBean annotation = testClass.getAnnotation(MockitoBean.class);
List<BeanOverrideHandler> handlers = processor.createHandlers(annotation, testClass);
assertThat(handlers).satisfiesExactly(
handler1 -> {
assertThat(handler1.getField()).isNull();
assertThat(handler1.getBeanName()).isNull();
assertThat(handler1.getBeanType().resolve()).isEqualTo(Integer.class);
},
handler2 -> {
assertThat(handler2.getField()).isNull();
assertThat(handler2.getBeanName()).isNull();
assertThat(handler2.getBeanType().resolve()).isEqualTo(Float.class);
}
);
}
static class TestCase {
@Nullable
@MockitoBean
@MockitoSpyBean
Integer number;
static class MissingTypesTestCase {
}
@MockitoBean(name = "bogus", types = { Integer.class, Float.class })
static class NameNotSupportedWithMultipleTypesTestCase {
}
@MockitoBean(types = Integer.class)
static class SingleMockByTypeTestCase {
}
@MockitoBean(name = "enigma", types = Integer.class)
static class SingleMockByNameTestCase {
}
@MockitoBean(types = { Integer.class, Float.class })
static class MultipleMocksTestCase {
}
}
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright 2002-2025 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.mockbeans;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.bean.override.example.ExampleService;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.context.bean.override.mockito.MockitoBeans;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
/**
* Integration tests for {@link MockitoBeans @MockitoBeans} and
* {@link MockitoBean @MockitoBean} declared "by name" at the class level as a
* repeatable annotation.
*
* @author Sam Brannen
* @since 6.2.2
* @see <a href="https://github.com/spring-projects/spring-framework/issues/33925">gh-33925</a>
* @see MockitoBeansByTypeIntegrationTests
*/
@SpringJUnitConfig
@MockitoBean(name = "s1", types = ExampleService.class)
@MockitoBean(name = "s2", types = ExampleService.class)
class MockitoBeansByNameIntegrationTests {
@Autowired
ExampleService s1;
@Autowired
ExampleService s2;
@MockitoBean(name = "s3")
ExampleService service3;
@Autowired
@Qualifier("s4")
ExampleService service4;
@BeforeEach
void configureMocks() {
given(s1.greeting()).willReturn("mock 1");
given(s2.greeting()).willReturn("mock 2");
given(service3.greeting()).willReturn("mock 3");
}
@Test
void checkMocksAndStandardBean() {
assertThat(s1.greeting()).isEqualTo("mock 1");
assertThat(s2.greeting()).isEqualTo("mock 2");
assertThat(service3.greeting()).isEqualTo("mock 3");
assertThat(service4.greeting()).isEqualTo("prod 4");
}
@Configuration
static class Config {
@Bean
ExampleService s1() {
return () -> "prod 1";
}
@Bean
ExampleService s2() {
return () -> "prod 2";
}
@Bean
ExampleService s3() {
return () -> "prod 3";
}
@Bean
ExampleService s4() {
return () -> "prod 4";
}
}
}

View File

@@ -0,0 +1,147 @@
/*
* Copyright 2002-2025 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.mockbeans;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.context.bean.override.mockito.MockitoBeans;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
/**
* Integration tests for {@link MockitoBeans @MockitoBeans} and
* {@link MockitoBean @MockitoBean} declared "by type" at the class level, as a
* repeatable annotation, and via a custom composed annotation.
*
* @author Sam Brannen
* @since 6.2.2
* @see <a href="https://github.com/spring-projects/spring-framework/issues/33925">gh-33925</a>
* @see MockitoBeansByNameIntegrationTests
*/
@SpringJUnitConfig
@MockitoBean(types = {Service04.class, Service05.class})
@SharedMocks // Intentionally declared between local @MockitoBean declarations
@MockitoBean(types = Service06.class)
class MockitoBeansByTypeIntegrationTests implements TestInterface01 {
@Autowired
Service01 service01;
@Autowired
Service02 service02;
@Autowired
Service03 service03;
@Autowired
Service04 service04;
@Autowired
Service05 service05;
@Autowired
Service06 service06;
@MockitoBean
Service07 service07;
@BeforeEach
void configureMocks() {
given(service01.greeting()).willReturn("mock 01");
given(service02.greeting()).willReturn("mock 02");
given(service03.greeting()).willReturn("mock 03");
given(service04.greeting()).willReturn("mock 04");
given(service05.greeting()).willReturn("mock 05");
given(service06.greeting()).willReturn("mock 06");
given(service07.greeting()).willReturn("mock 07");
}
@Test
void checkMocks() {
assertThat(service01.greeting()).isEqualTo("mock 01");
assertThat(service02.greeting()).isEqualTo("mock 02");
assertThat(service03.greeting()).isEqualTo("mock 03");
assertThat(service04.greeting()).isEqualTo("mock 04");
assertThat(service05.greeting()).isEqualTo("mock 05");
assertThat(service06.greeting()).isEqualTo("mock 06");
assertThat(service07.greeting()).isEqualTo("mock 07");
}
@MockitoBean(types = Service09.class)
static class BaseTestCase implements TestInterface08 {
@Autowired
Service08 service08;
@Autowired
Service09 service09;
@MockitoBean
Service10 service10;
}
@Nested
@MockitoBean(types = Service12.class)
class NestedTests extends BaseTestCase implements TestInterface11 {
@Autowired
Service11 service11;
@Autowired
Service12 service12;
@MockitoBean
Service13 service13;
@BeforeEach
void configureMocks() {
given(service08.greeting()).willReturn("mock 08");
given(service09.greeting()).willReturn("mock 09");
given(service10.greeting()).willReturn("mock 10");
given(service11.greeting()).willReturn("mock 11");
given(service12.greeting()).willReturn("mock 12");
given(service13.greeting()).willReturn("mock 13");
}
@Test
void checkMocks() {
assertThat(service01.greeting()).isEqualTo("mock 01");
assertThat(service02.greeting()).isEqualTo("mock 02");
assertThat(service03.greeting()).isEqualTo("mock 03");
assertThat(service04.greeting()).isEqualTo("mock 04");
assertThat(service05.greeting()).isEqualTo("mock 05");
assertThat(service06.greeting()).isEqualTo("mock 06");
assertThat(service07.greeting()).isEqualTo("mock 07");
assertThat(service08.greeting()).isEqualTo("mock 08");
assertThat(service09.greeting()).isEqualTo("mock 09");
assertThat(service10.greeting()).isEqualTo("mock 10");
assertThat(service11.greeting()).isEqualTo("mock 11");
assertThat(service12.greeting()).isEqualTo("mock 12");
assertThat(service13.greeting()).isEqualTo("mock 13");
}
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2002-2025 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.mockbeans;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.springframework.core.ResolvableType;
import org.springframework.test.context.bean.override.BeanOverrideHandler;
import org.springframework.test.context.bean.override.BeanOverrideTestUtils;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.context.bean.override.mockito.MockitoBeans;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link MockitoBeans @MockitoBeans}: {@link MockitoBean @MockitoBean}
* declared at the class level, as a repeatable annotation, and via a custom composed
* annotation.
*
* @author Sam Brannen
* @since 6.2.2
* @see <a href="https://github.com/spring-projects/spring-framework/issues/33925">gh-33925</a>
*/
class MockitoBeansTests {
@Test
void registrationOrderForTopLevelClass() {
Stream<Class<?>> mockedServices = getRegisteredMockTypes(MockitoBeansByTypeIntegrationTests.class);
assertThat(mockedServices).containsExactly(
Service01.class, Service02.class, Service03.class, Service04.class,
Service05.class, Service06.class, Service07.class);
}
@Test
void registrationOrderForNestedClass() {
Stream<Class<?>> mockedServices = getRegisteredMockTypes(MockitoBeansByTypeIntegrationTests.NestedTests.class);
assertThat(mockedServices).containsExactly(
Service01.class, Service02.class, Service03.class, Service04.class,
Service05.class, Service06.class, Service07.class, Service08.class,
Service09.class, Service10.class, Service11.class, Service12.class,
Service13.class);
}
private static Stream<Class<?>> getRegisteredMockTypes(Class<?> testClass) {
return BeanOverrideTestUtils.findAllHandlers(testClass)
.stream()
.map(BeanOverrideHandler::getBeanType)
.map(ResolvableType::getRawClass);
}
}

View File

@@ -0,0 +1,21 @@
/*
* Copyright 2002-2025 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.mockbeans;
interface Service {
String greeting();
}

View File

@@ -0,0 +1,20 @@
/*
* Copyright 2002-2025 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.mockbeans;
interface Service01 extends Service {
}

View File

@@ -0,0 +1,20 @@
/*
* Copyright 2002-2025 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.mockbeans;
interface Service02 extends Service {
}

View File

@@ -0,0 +1,20 @@
/*
* Copyright 2002-2025 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.mockbeans;
interface Service03 extends Service {
}

View File

@@ -0,0 +1,20 @@
/*
* Copyright 2002-2025 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.mockbeans;
interface Service04 extends Service {
}

View File

@@ -0,0 +1,20 @@
/*
* Copyright 2002-2025 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.mockbeans;
interface Service05 extends Service {
}

View File

@@ -0,0 +1,20 @@
/*
* Copyright 2002-2025 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.mockbeans;
interface Service06 extends Service {
}

View File

@@ -0,0 +1,20 @@
/*
* Copyright 2002-2025 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.mockbeans;
interface Service07 extends Service {
}

View File

@@ -0,0 +1,20 @@
/*
* Copyright 2002-2025 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.mockbeans;
interface Service08 extends Service {
}

View File

@@ -0,0 +1,20 @@
/*
* Copyright 2002-2025 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.mockbeans;
interface Service09 extends Service {
}

View File

@@ -0,0 +1,20 @@
/*
* Copyright 2002-2025 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.mockbeans;
interface Service10 extends Service {
}

View File

@@ -0,0 +1,20 @@
/*
* Copyright 2002-2025 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.mockbeans;
interface Service11 extends Service {
}

View File

@@ -0,0 +1,20 @@
/*
* Copyright 2002-2025 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.mockbeans;
interface Service12 extends Service {
}

View File

@@ -0,0 +1,20 @@
/*
* Copyright 2002-2025 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.mockbeans;
interface Service13 extends Service {
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2002-2025 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.mockbeans;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@MockitoBean(types = Service02.class)
@MockitoBean(types = Service03.class)
@interface SharedMocks {
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright 2002-2025 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.mockbeans;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
@MockitoBean(types = Service01.class)
interface TestInterface01 {
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright 2002-2025 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.mockbeans;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
@MockitoBean(types = Service08.class)
interface TestInterface08 {
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright 2002-2025 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.mockbeans;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
@MockitoBean(types = Service11.class)
interface TestInterface11 {
}