Add value attribute alias to @⁠MockitoBean and @⁠MockitoSpyBean

This commit improves the user experience for common use cases by
introducing new `value` attributes in @⁠MockitoBean and
@⁠MockitoSpyBean that are aliases for the existing `name` attributes.

For example, this allows developers to declare
@⁠MockitoBean("userService") instead of @⁠MockitoBean(name =
"userService"), analogous to the existing name/value alias support in
@⁠TestBean.

Closes gh-33680
This commit is contained in:
Sam Brannen
2024-10-10 13:05:33 +02:00
parent 1b8f2c46c1
commit 0e8316e704
12 changed files with 97 additions and 68 deletions

View File

@@ -17,12 +17,12 @@
package org.springframework.test.context.bean.override.mockito;
import org.junit.jupiter.api.Test;
import org.mockito.Answers;
import org.springframework.test.context.ContextCustomizer;
import org.springframework.test.context.bean.override.BeanOverrideContextCustomizerTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Answers.RETURNS_MOCKS;
/**
* Tests that validate the behavior of {@link MockitoBean} and
@@ -85,7 +85,7 @@ class MockitoBeanContextCustomizerEqualityTests {
static class Case1ByName {
@MockitoBean(name = "serviceBean")
@MockitoBean("serviceBean")
private String exampleService;
}
@@ -99,7 +99,7 @@ class MockitoBeanContextCustomizerEqualityTests {
static class Case2ByName {
@MockitoBean(name = "serviceBean")
@MockitoBean("serviceBean")
private String serviceToMock;
}
@@ -120,14 +120,14 @@ class MockitoBeanContextCustomizerEqualityTests {
static class Case3 {
@MockitoBean(answers = Answers.RETURNS_MOCKS)
@MockitoBean(answers = RETURNS_MOCKS)
private String exampleService;
}
static class Case4ByName {
@MockitoSpyBean(name = "serviceBean")
@MockitoSpyBean("serviceBean")
private String exampleService;
}
@@ -141,7 +141,7 @@ class MockitoBeanContextCustomizerEqualityTests {
static class Case5ByName {
@MockitoSpyBean(name = "serviceBean")
@MockitoSpyBean("serviceBean")
private String serviceToMock;
}

View File

@@ -36,22 +36,22 @@ import static org.assertj.core.api.Assertions.assertThat;
@SpringJUnitConfig
public class MockitoBeanForByNameLookupIntegrationTests {
@MockitoBean(name = "field")
@MockitoBean("field")
ExampleService field;
@MockitoBean(name = "nestedField")
@MockitoBean("nestedField")
ExampleService nestedField;
@MockitoBean(name = "field")
@MockitoBean("field")
ExampleService renamed1;
@MockitoBean(name = "nestedField")
@MockitoBean("nestedField")
ExampleService renamed2;
@MockitoBean(name = "nonExistingBean")
@MockitoBean("nonExistingBean")
ExampleService nonExisting1;
@MockitoBean(name = "nestedNonExistingBean")
@MockitoBean("nestedNonExistingBean")
ExampleService nonExisting2;

View File

@@ -24,6 +24,7 @@ import org.junit.jupiter.api.Test;
import org.mockito.Answers;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.test.context.bean.override.OverrideMetadata;
import org.springframework.util.ReflectionUtils;
@@ -114,7 +115,7 @@ class MockitoBeanOverrideMetadataTests {
}
private MockitoBeanOverrideMetadata createMetadata(Field field) {
MockitoBean annotation = field.getAnnotation(MockitoBean.class);
MockitoBean annotation = AnnotatedElementUtils.getMergedAnnotation(field, MockitoBean.class);
return new MockitoBeanOverrideMetadata(field, ResolvableType.forClass(field.getType()), annotation);
}
@@ -128,7 +129,7 @@ class MockitoBeanOverrideMetadataTests {
static class SampleOneMockWithName {
@MockitoBean(name = "anotherService")
@MockitoBean("anotherService")
String service;
}
@@ -144,7 +145,7 @@ class MockitoBeanOverrideMetadataTests {
@MockitoBean(name = "beanToMock")
private String service3;
@MockitoBean(name = "beanToMock")
@MockitoBean(value = "beanToMock")
private String service4;
@MockitoBean(extraInterfaces = Externalizable.class)

View File

@@ -26,7 +26,6 @@ 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.mockito.quality.Strictness;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.annotation.DirtiesContext;
@@ -42,6 +41,7 @@ import static org.junit.platform.testkit.engine.TestExecutionResultConditions.me
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.BDDMockito.when;
import static org.mockito.Mockito.mock;
import static org.mockito.quality.Strictness.STRICT_STUBS;
/**
* Integration tests ensuring unnecessary stubbing is reported in various
@@ -85,7 +85,7 @@ class MockitoBeanSettingsStrictIntegrationTests {
@SpringJUnitConfig(Config.class)
@DirtiesContext
@MockitoBeanSettings(Strictness.STRICT_STUBS)
@MockitoBeanSettings(STRICT_STUBS)
static class ExplicitStrictness extends BaseCase {
}

View File

@@ -33,6 +33,7 @@ import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.springframework.test.context.bean.override.mockito.MockReset.BEFORE;
/**
* Integration tests for {@link MockitoBean} that validate automatic reset
@@ -45,10 +46,10 @@ import static org.mockito.Mockito.doReturn;
@TestMethodOrder(OrderAnnotation.class)
public class MockitoBeanWithResetIntegrationTests {
@MockitoBean(reset = MockReset.BEFORE)
@MockitoBean(reset = BEFORE)
ExampleService service;
@MockitoBean(reset = MockReset.BEFORE)
@MockitoBean(reset = BEFORE)
FailingExampleService failingService;
@Order(1)

View File

@@ -40,16 +40,16 @@ import static org.assertj.core.api.Assertions.assertThat;
@SpringJUnitConfig(Config.class)
public class MockitoSpyBeanForByNameLookupIntegrationTests {
@MockitoSpyBean(name = "field")
@MockitoSpyBean("field")
ExampleService field;
@MockitoSpyBean(name = "nestedField")
@MockitoSpyBean("nestedField")
ExampleService nestedField;
@MockitoSpyBean(name = "field")
@MockitoSpyBean("field")
ExampleService renamed1;
@MockitoSpyBean(name = "nestedField")
@MockitoSpyBean("nestedField")
ExampleService renamed2;

View File

@@ -22,6 +22,7 @@ import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.test.context.bean.override.OverrideMetadata;
import org.springframework.util.ReflectionUtils;
@@ -105,7 +106,7 @@ class MockitoSpyBeanOverrideMetadataTests {
}
private MockitoSpyBeanOverrideMetadata createMetadata(Field field) {
MockitoSpyBean annotation = field.getAnnotation(MockitoSpyBean.class);
MockitoSpyBean annotation = AnnotatedElementUtils.getMergedAnnotation(field, MockitoSpyBean.class);
return new MockitoSpyBeanOverrideMetadata(field, ResolvableType.forClass(field.getType()), annotation);
}
@@ -119,7 +120,7 @@ class MockitoSpyBeanOverrideMetadataTests {
static class SampleOneSpyWithName {
@MockitoSpyBean(name = "anotherService")
@MockitoSpyBean("anotherService")
String service;
}
@@ -132,10 +133,10 @@ class MockitoSpyBeanOverrideMetadataTests {
@MockitoSpyBean
private String service2;
@MockitoSpyBean(name = "beanToMock")
@MockitoSpyBean(name = "beanToSpy")
private String service3;
@MockitoSpyBean(name = "beanToMock")
@MockitoSpyBean(value = "beanToSpy")
private String service4;
@MockitoSpyBean(reset = MockReset.BEFORE)

View File

@@ -81,7 +81,7 @@ class MockitoSpyBeanTests {
static class ByNameSingleLookup {
@MockitoSpyBean(name = "beanToSpy")
@MockitoSpyBean("beanToSpy")
String example;
}

View File

@@ -22,11 +22,9 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.Nullable;
import org.springframework.test.context.bean.override.example.ExampleService;
import org.springframework.test.context.bean.override.example.FailingExampleService;
import org.springframework.test.context.bean.override.example.RealExampleService;
@@ -35,6 +33,7 @@ import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.mockito.Mockito.doReturn;
import static org.springframework.test.context.bean.override.mockito.MockReset.BEFORE;
/**
* Integration tests for {@link MockitoSpyBean} that validate automatic reset
@@ -47,12 +46,13 @@ import static org.mockito.Mockito.doReturn;
@TestMethodOrder(OrderAnnotation.class)
public class MockitoSpyBeanWithResetIntegrationTests {
@MockitoSpyBean(reset = MockReset.BEFORE)
@MockitoSpyBean(reset = BEFORE)
ExampleService service;
@MockitoSpyBean(reset = MockReset.BEFORE)
@MockitoSpyBean(name = "failingExampleServiceFactory", reset = BEFORE)
FailingExampleService failingService;
@Order(1)
@Test
void beanFirstEstablishingStub(ApplicationContext ctx) {
@@ -83,21 +83,23 @@ public class MockitoSpyBeanWithResetIntegrationTests {
@Order(4)
@Test
void factoryBeanSecondEnsuringStubReset(ApplicationContext ctx) {
assertThat(ctx.getBean("factory")).isNotNull().isSameAs(this.failingService);
assertThat(ctx.getBean("failingExampleServiceFactory"))
.isNotNull()
.isSameAs(this.failingService);
assertThatIllegalStateException().isThrownBy(this.failingService::greeting)
.as("not stubbed")
.withMessage("Failed");
}
static class FailingExampleServiceFactory implements FactoryBean<FailingExampleService> {
@Nullable
@Override
public FailingExampleService getObject() {
return new FailingExampleService();
}
@Nullable
@Override
public Class<?> getObjectType() {
return FailingExampleService.class;
@@ -107,14 +109,13 @@ public class MockitoSpyBeanWithResetIntegrationTests {
@Configuration(proxyBeanMethods = false)
static class Config {
@Bean("service")
ExampleService bean1() {
@Bean
ExampleService service() {
return new RealExampleService("Production hello");
}
@Bean("factory")
@Qualifier("factory")
FailingExampleServiceFactory factory() {
@Bean
FailingExampleServiceFactory failingExampleServiceFactory() {
return new FailingExampleServiceFactory();
}
}