Skip to content

Commit 64be6ae

Browse files
committed
2 parents a32cd19 + bc35722 commit 64be6ae

File tree

3 files changed

+296
-58
lines changed

3 files changed

+296
-58
lines changed

spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessor.java

Lines changed: 49 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.beans.PropertyDescriptor;
2020
import java.lang.reflect.Field;
2121
import java.util.Arrays;
22+
import java.util.Collection;
2223
import java.util.HashMap;
2324
import java.util.LinkedHashMap;
2425
import java.util.LinkedHashSet;
@@ -85,14 +86,14 @@ public class MockitoPostProcessor extends InstantiationAwareBeanPostProcessorAda
8586
.getQualifiedAttributeName(ConfigurationClassPostProcessor.class,
8687
"configurationClass");
8788

89+
private static final BeanNameGenerator beanNameGenerator = new DefaultBeanNameGenerator();
90+
8891
private final Set<Definition> definitions;
8992

9093
private ClassLoader classLoader;
9194

9295
private BeanFactory beanFactory;
9396

94-
private final BeanNameGenerator beanNameGenerator = new DefaultBeanNameGenerator();
95-
9697
private final MockitoBeans mockitoBeans = new MockitoBeans();
9798

9899
private Map<Definition, String> beanNameRegistry = new HashMap<>();
@@ -183,13 +184,13 @@ private void registerMock(ConfigurableListableBeanFactory beanFactory,
183184
RootBeanDefinition beanDefinition = createBeanDefinition(definition);
184185
String beanName = getBeanName(beanFactory, registry, definition, beanDefinition);
185186
String transformedBeanName = BeanFactoryUtils.transformedBeanName(beanName);
186-
beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(1,
187-
beanName);
188187
if (registry.containsBeanDefinition(transformedBeanName)) {
188+
BeanDefinition existing = registry.getBeanDefinition(transformedBeanName);
189+
copyBeanDefinitionDetails(existing, beanDefinition);
189190
registry.removeBeanDefinition(transformedBeanName);
190191
}
191192
registry.registerBeanDefinition(transformedBeanName, beanDefinition);
192-
Object mock = createMock(definition, beanName);
193+
Object mock = definition.createMock(beanName + " bean");
193194
beanFactory.registerSingleton(transformedBeanName, mock);
194195
this.mockitoBeans.add(mock);
195196
this.beanNameRegistry.put(definition, beanName);
@@ -202,84 +203,79 @@ private RootBeanDefinition createBeanDefinition(MockDefinition mockDefinition) {
202203
RootBeanDefinition definition = new RootBeanDefinition(
203204
mockDefinition.getTypeToMock().resolve());
204205
definition.setTargetType(mockDefinition.getTypeToMock());
205-
definition.setFactoryBeanName(BEAN_NAME);
206-
definition.setFactoryMethodName("createMock");
207-
definition.getConstructorArgumentValues().addIndexedArgumentValue(0,
208-
mockDefinition);
209206
if (mockDefinition.getQualifier() != null) {
210207
mockDefinition.getQualifier().applyTo(definition);
211208
}
212209
return definition;
213210
}
214211

215-
/**
216-
* Factory method used by defined beans to actually create the mock.
217-
* @param mockDefinition the mock definition
218-
* @param name the bean name
219-
* @return the mock instance
220-
*/
221-
protected final Object createMock(MockDefinition mockDefinition, String name) {
222-
return mockDefinition.createMock(name + " bean");
223-
}
224-
225212
private String getBeanName(ConfigurableListableBeanFactory beanFactory,
226213
BeanDefinitionRegistry registry, MockDefinition mockDefinition,
227214
RootBeanDefinition beanDefinition) {
228215
if (StringUtils.hasLength(mockDefinition.getName())) {
229216
return mockDefinition.getName();
230217
}
231-
Set<String> existingBeans = findCandidateBeans(beanFactory, mockDefinition);
218+
Set<String> existingBeans = getExistingBeans(beanFactory,
219+
mockDefinition.getTypeToMock(), mockDefinition.getQualifier());
232220
if (existingBeans.isEmpty()) {
233-
return this.beanNameGenerator.generateBeanName(beanDefinition, registry);
221+
return MockitoPostProcessor.beanNameGenerator.generateBeanName(beanDefinition,
222+
registry);
234223
}
235224
if (existingBeans.size() == 1) {
236225
return existingBeans.iterator().next();
237226
}
227+
String primaryCandidate = determinePrimaryCandidate(registry, existingBeans,
228+
mockDefinition.getTypeToMock());
229+
if (primaryCandidate != null) {
230+
return primaryCandidate;
231+
}
238232
throw new IllegalStateException(
239233
"Unable to register mock bean " + mockDefinition.getTypeToMock()
240234
+ " expected a single matching bean to replace but found "
241235
+ existingBeans);
242236
}
243237

238+
private void copyBeanDefinitionDetails(BeanDefinition from, RootBeanDefinition to) {
239+
to.setPrimary(from.isPrimary());
240+
}
241+
244242
private void registerSpy(ConfigurableListableBeanFactory beanFactory,
245-
BeanDefinitionRegistry registry, SpyDefinition definition, Field field) {
246-
String[] existingBeans = getExistingBeans(beanFactory, definition.getTypeToSpy());
243+
BeanDefinitionRegistry registry, SpyDefinition spyDefinition, Field field) {
244+
Set<String> existingBeans = getExistingBeans(beanFactory,
245+
spyDefinition.getTypeToSpy(), spyDefinition.getQualifier());
247246
if (ObjectUtils.isEmpty(existingBeans)) {
248-
createSpy(registry, definition, field);
247+
createSpy(registry, spyDefinition, field);
249248
}
250249
else {
251-
registerSpies(registry, definition, field, existingBeans);
250+
registerSpies(registry, spyDefinition, field, existingBeans);
252251
}
253252
}
254253

255-
private Set<String> findCandidateBeans(ConfigurableListableBeanFactory beanFactory,
256-
MockDefinition mockDefinition) {
257-
QualifierDefinition qualifier = mockDefinition.getQualifier();
254+
private Set<String> getExistingBeans(ConfigurableListableBeanFactory beanFactory,
255+
ResolvableType type, QualifierDefinition qualifier) {
258256
Set<String> candidates = new TreeSet<>();
259-
for (String candidate : getExistingBeans(beanFactory,
260-
mockDefinition.getTypeToMock())) {
257+
for (String candidate : getExistingBeans(beanFactory, type)) {
261258
if (qualifier == null || qualifier.matches(beanFactory, candidate)) {
262259
candidates.add(candidate);
263260
}
264261
}
265262
return candidates;
266263
}
267264

268-
private String[] getExistingBeans(ConfigurableListableBeanFactory beanFactory,
265+
private Set<String> getExistingBeans(ConfigurableListableBeanFactory beanFactory,
269266
ResolvableType type) {
270267
Set<String> beans = new LinkedHashSet<>(
271268
Arrays.asList(beanFactory.getBeanNamesForType(type)));
272-
String resolvedTypeName = type.resolve(Object.class).getName();
269+
String typeName = type.resolve(Object.class).getName();
273270
for (String beanName : beanFactory.getBeanNamesForType(FactoryBean.class)) {
274271
beanName = BeanFactoryUtils.transformedBeanName(beanName);
275272
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
276-
if (resolvedTypeName
277-
.equals(beanDefinition.getAttribute(FACTORY_BEAN_OBJECT_TYPE))) {
273+
if (typeName.equals(beanDefinition.getAttribute(FACTORY_BEAN_OBJECT_TYPE))) {
278274
beans.add(beanName);
279275
}
280276
}
281277
beans.removeIf(this::isScopedTarget);
282-
return StringUtils.toStringArray(beans);
278+
return beans;
283279
}
284280

285281
private boolean isScopedTarget(String beanName) {
@@ -291,49 +287,49 @@ private boolean isScopedTarget(String beanName) {
291287
}
292288
}
293289

294-
private void createSpy(BeanDefinitionRegistry registry, SpyDefinition definition,
290+
private void createSpy(BeanDefinitionRegistry registry, SpyDefinition spyDefinition,
295291
Field field) {
296292
RootBeanDefinition beanDefinition = new RootBeanDefinition(
297-
definition.getTypeToSpy().resolve());
298-
String beanName = this.beanNameGenerator.generateBeanName(beanDefinition,
299-
registry);
293+
spyDefinition.getTypeToSpy().resolve());
294+
String beanName = MockitoPostProcessor.beanNameGenerator
295+
.generateBeanName(beanDefinition, registry);
300296
registry.registerBeanDefinition(beanName, beanDefinition);
301-
registerSpy(definition, field, beanName);
297+
registerSpy(spyDefinition, field, beanName);
302298
}
303299

304-
private void registerSpies(BeanDefinitionRegistry registry, SpyDefinition definition,
305-
Field field, String[] existingBeans) {
300+
private void registerSpies(BeanDefinitionRegistry registry,
301+
SpyDefinition spyDefinition, Field field, Collection<String> existingBeans) {
306302
try {
307-
registerSpy(definition, field,
308-
determineBeanName(existingBeans, definition, registry));
303+
String beanName = determineBeanName(existingBeans, spyDefinition, registry);
304+
registerSpy(spyDefinition, field, beanName);
309305
}
310306
catch (RuntimeException ex) {
311307
throw new IllegalStateException(
312-
"Unable to register spy bean " + definition.getTypeToSpy(), ex);
308+
"Unable to register spy bean " + spyDefinition.getTypeToSpy(), ex);
313309
}
314310
}
315311

316-
private String determineBeanName(String[] existingBeans, SpyDefinition definition,
317-
BeanDefinitionRegistry registry) {
312+
private String determineBeanName(Collection<String> existingBeans,
313+
SpyDefinition definition, BeanDefinitionRegistry registry) {
318314
if (StringUtils.hasText(definition.getName())) {
319315
return definition.getName();
320316
}
321-
if (existingBeans.length == 1) {
322-
return existingBeans[0];
317+
if (existingBeans.size() == 1) {
318+
return existingBeans.iterator().next();
323319
}
324320
return determinePrimaryCandidate(registry, existingBeans,
325321
definition.getTypeToSpy());
326322
}
327323

328324
private String determinePrimaryCandidate(BeanDefinitionRegistry registry,
329-
String[] candidateBeanNames, ResolvableType type) {
325+
Collection<String> candidateBeanNames, ResolvableType type) {
330326
String primaryBeanName = null;
331327
for (String candidateBeanName : candidateBeanNames) {
332328
BeanDefinition beanDefinition = registry.getBeanDefinition(candidateBeanName);
333329
if (beanDefinition.isPrimary()) {
334330
if (primaryBeanName != null) {
335331
throw new NoUniqueBeanDefinitionException(type.resolve(),
336-
candidateBeanNames.length,
332+
candidateBeanNames.size(),
337333
"more than one 'primary' bean found among candidates: "
338334
+ Arrays.asList(candidateBeanNames));
339335
}
@@ -351,7 +347,7 @@ private void registerSpy(SpyDefinition definition, Field field, String beanName)
351347
}
352348
}
353349

354-
protected Object createSpyIfNecessary(Object bean, String beanName)
350+
protected final Object createSpyIfNecessary(Object bean, String beanName)
355351
throws BeansException {
356352
SpyDefinition definition = this.spies.get(beanName);
357353
if (definition != null) {
@@ -480,7 +476,7 @@ public int getOrder() {
480476
@Override
481477
public Object getEarlyBeanReference(Object bean, String beanName)
482478
throws BeansException {
483-
return createSpyIfNecessary(bean, beanName);
479+
return this.mockitoPostProcessor.createSpyIfNecessary(bean, beanName);
484480
}
485481

486482
@Override
@@ -489,10 +485,6 @@ public Object postProcessAfterInitialization(Object bean, String beanName)
489485
if (bean instanceof FactoryBean) {
490486
return bean;
491487
}
492-
return createSpyIfNecessary(bean, beanName);
493-
}
494-
495-
private Object createSpyIfNecessary(Object bean, String beanName) {
496488
return this.mockitoPostProcessor.createSpyIfNecessary(bean, beanName);
497489
}
498490

0 commit comments

Comments
 (0)