diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessor.java b/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessor.java index 6ff5666169..bcfee98d19 100644 --- a/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessor.java +++ b/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * Copyright 2012-2017 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. @@ -37,7 +37,6 @@ import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.NoUniqueBeanDefinitionException; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; @@ -311,16 +310,9 @@ public class MockitoPostProcessor extends InstantiationAwareBeanPostProcessorAda private void registerSpies(BeanDefinitionRegistry registry, SpyDefinition definition, Field field, String[] existingBeans) { - ResolvableType type = definition.getTypeToSpy(); try { - if (ObjectUtils.isEmpty(existingBeans)) { - throw new NoSuchBeanDefinitionException(type); - } - if (existingBeans.length > 1) { - existingBeans = new String[] { - determinePrimaryCandidate(registry, existingBeans, type) }; - } - registerSpy(definition, field, existingBeans[0]); + registerSpy(definition, field, + determineBeanName(existingBeans, definition, registry)); } catch (RuntimeException ex) { throw new IllegalStateException( @@ -328,6 +320,18 @@ public class MockitoPostProcessor extends InstantiationAwareBeanPostProcessorAda } } + private String determineBeanName(String[] existingBeans, SpyDefinition definition, + BeanDefinitionRegistry registry) { + if (StringUtils.hasText(definition.getName())) { + return definition.getName(); + } + if (existingBeans.length == 1) { + return existingBeans[0]; + } + return determinePrimaryCandidate(registry, existingBeans, + definition.getTypeToSpy()); + } + private String determinePrimaryCandidate(BeanDefinitionRegistry registry, String[] candidateBeanNames, ResolvableType type) { String primaryBeanName = null; diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/SpyBeanOnTestFieldForMultipleExistingBeansIntegrationTests.java b/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/SpyBeanOnTestFieldForMultipleExistingBeansWithOnePrimaryIntegrationTests.java similarity index 90% rename from spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/SpyBeanOnTestFieldForMultipleExistingBeansIntegrationTests.java rename to spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/SpyBeanOnTestFieldForMultipleExistingBeansWithOnePrimaryIntegrationTests.java index c4880c533d..c6933bd322 100644 --- a/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/SpyBeanOnTestFieldForMultipleExistingBeansIntegrationTests.java +++ b/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/SpyBeanOnTestFieldForMultipleExistingBeansWithOnePrimaryIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * Copyright 2012-2017 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. @@ -33,12 +33,13 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; /** - * Test {@link SpyBean} on a test class field can be used to inject new spy instances. + * Test {@link SpyBean} on a test class field can be used to inject a spy instance when + * there are multiple candidates and one is primary. * * @author Phillip Webb */ @RunWith(SpringRunner.class) -public class SpyBeanOnTestFieldForMultipleExistingBeansIntegrationTests { +public class SpyBeanOnTestFieldForMultipleExistingBeansWithOnePrimaryIntegrationTests { @SpyBean private SimpleExampleStringGenericService spy; diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/SpyBeanWithNameOnTestFieldForMultipleExistingBeansTests.java b/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/SpyBeanWithNameOnTestFieldForMultipleExistingBeansTests.java new file mode 100644 index 0000000000..b5437036ca --- /dev/null +++ b/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/SpyBeanWithNameOnTestFieldForMultipleExistingBeansTests.java @@ -0,0 +1,64 @@ +/* + * Copyright 2012-2017 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 + * + * http://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.boot.test.mock.mockito; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.internal.util.MockUtil; + +import org.springframework.boot.test.mock.mockito.example.SimpleExampleStringGenericService; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Test {@link SpyBean} on a test class field can be used to inject a spy instance when + * there are multiple candidates and one is chosen using the name attribute. + * + * @author Phillip Webb + * @author Andy Wilkinson + */ +@RunWith(SpringRunner.class) +public class SpyBeanWithNameOnTestFieldForMultipleExistingBeansTests { + + @SpyBean(name = "two") + private SimpleExampleStringGenericService spy; + + @Test + public void testSpying() throws Exception { + assertThat(new MockUtil().isSpy(this.spy)).isTrue(); + assertThat(new MockUtil().getMockName(this.spy).toString()).isEqualTo("two"); + } + + @Configuration + static class Config { + + @Bean + public SimpleExampleStringGenericService one() { + return new SimpleExampleStringGenericService("one"); + } + + @Bean + public SimpleExampleStringGenericService two() { + return new SimpleExampleStringGenericService("two"); + } + + } + +}