Prevent early initialization in MockitoPostProcessor
Fixes gh-20665
This commit is contained in:
parent
102729b5e1
commit
b9c2b7b257
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2019 the original author or authors.
|
* Copyright 2012-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -247,9 +247,9 @@ public class MockitoPostProcessor extends InstantiationAwareBeanPostProcessorAda
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<String> getExistingBeans(ConfigurableListableBeanFactory beanFactory, ResolvableType type) {
|
private Set<String> getExistingBeans(ConfigurableListableBeanFactory beanFactory, ResolvableType type) {
|
||||||
Set<String> beans = new LinkedHashSet<>(Arrays.asList(beanFactory.getBeanNamesForType(type)));
|
Set<String> beans = new LinkedHashSet<>(Arrays.asList(beanFactory.getBeanNamesForType(type, true, false)));
|
||||||
String typeName = type.resolve(Object.class).getName();
|
String typeName = type.resolve(Object.class).getName();
|
||||||
for (String beanName : beanFactory.getBeanNamesForType(FactoryBean.class)) {
|
for (String beanName : beanFactory.getBeanNamesForType(FactoryBean.class, true, false)) {
|
||||||
beanName = BeanFactoryUtils.transformedBeanName(beanName);
|
beanName = BeanFactoryUtils.transformedBeanName(beanName);
|
||||||
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
|
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
|
||||||
if (typeName.equals(beanDefinition.getAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE))) {
|
if (typeName.equals(beanDefinition.getAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE))) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2019 the original author or authors.
|
* Copyright 2012-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -16,11 +16,18 @@
|
||||||
|
|
||||||
package org.springframework.boot.test.mock.mockito;
|
package org.springframework.boot.test.mock.mockito;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
import org.springframework.beans.BeanWrapper;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||||
|
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||||
import org.springframework.boot.test.mock.mockito.example.ExampleService;
|
import org.springframework.boot.test.mock.mockito.example.ExampleService;
|
||||||
import org.springframework.boot.test.mock.mockito.example.FailingExampleService;
|
import org.springframework.boot.test.mock.mockito.example.FailingExampleService;
|
||||||
|
|
@ -29,6 +36,9 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Primary;
|
import org.springframework.context.annotation.Primary;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||||
|
|
@ -39,6 +49,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
* @author Andreas Neiser
|
* @author Andreas Neiser
|
||||||
|
* @author Madhura Bhave
|
||||||
*/
|
*/
|
||||||
class MockitoPostProcessorTests {
|
class MockitoPostProcessorTests {
|
||||||
|
|
||||||
|
|
@ -123,6 +134,16 @@ class MockitoPostProcessorTests {
|
||||||
assertThat(Mockito.mockingDetails(context.getBean("exampleQualified", ExampleService.class)).isSpy()).isTrue();
|
assertThat(Mockito.mockingDetails(context.getBean("exampleQualified", ExampleService.class)).isSpy()).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void postProcessorShouldNotTriggerEarlyInitialization() {
|
||||||
|
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||||
|
context.register(FactoryBeanRegisteringPostProcessor.class);
|
||||||
|
MockitoPostProcessor.register(context);
|
||||||
|
context.register(TestBeanFactoryPostProcessor.class);
|
||||||
|
context.register(EagerInitBean.class);
|
||||||
|
context.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@MockBean(SomeInterface.class)
|
@MockBean(SomeInterface.class)
|
||||||
static class MockedFactoryBean {
|
static class MockedFactoryBean {
|
||||||
|
|
@ -258,6 +279,14 @@ class MockitoPostProcessorTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
static class EagerInitBean {
|
||||||
|
|
||||||
|
@MockBean
|
||||||
|
private ExampleService service;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static class TestFactoryBean implements FactoryBean<Object> {
|
static class TestFactoryBean implements FactoryBean<Object> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -275,6 +304,33 @@ class MockitoPostProcessorTests {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
static class FactoryBeanRegisteringPostProcessor implements BeanFactoryPostProcessor, Ordered {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||||
|
RootBeanDefinition beanDefinition = new RootBeanDefinition(TestFactoryBean.class);
|
||||||
|
((BeanDefinitionRegistry) beanFactory).registerBeanDefinition("test", beanDefinition);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOrder() {
|
||||||
|
return Ordered.HIGHEST_PRECEDENCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class TestBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||||
|
Map<String, BeanWrapper> cache = (Map<String, BeanWrapper>) ReflectionTestUtils.getField(beanFactory,
|
||||||
|
"factoryBeanInstanceCache");
|
||||||
|
Assert.isTrue(cache.isEmpty(), "Early initialization of factory bean triggered.");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SomeInterface {
|
interface SomeInterface {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue