Skip to content

Commit 70e802f

Browse files
committed
Use name from @SpyBean to disambiguate multiple candidates
Previously, @SpyBean's name attribute was not used when determining the name of the bean to spy upon. When there were multiple candidates, none of which were primary, this would lead to a failure to find the bean to spy upon. This behaviour is also inconsistent with @MockBean which does use the name attribute to identify the bean to mock. This commit updates MockitoPostProcessor to use the name attribute, when set, to identify the bean that should be spied upon. For consistency with @MockBean it is always used when set. When not set the previous logic will continue to be used. Closes gh-8315
1 parent 1abd91d commit 70e802f

File tree

3 files changed

+83
-14
lines changed

3 files changed

+83
-14
lines changed

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

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2016 the original author or authors.
2+
* Copyright 2012-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -37,7 +37,6 @@
3737
import org.springframework.beans.factory.BeanFactoryAware;
3838
import org.springframework.beans.factory.BeanFactoryUtils;
3939
import org.springframework.beans.factory.FactoryBean;
40-
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
4140
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
4241
import org.springframework.beans.factory.config.BeanDefinition;
4342
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
@@ -311,23 +310,28 @@ private void createSpy(BeanDefinitionRegistry registry, SpyDefinition definition
311310

312311
private void registerSpies(BeanDefinitionRegistry registry, SpyDefinition definition,
313312
Field field, String[] existingBeans) {
314-
ResolvableType type = definition.getTypeToSpy();
315313
try {
316-
if (ObjectUtils.isEmpty(existingBeans)) {
317-
throw new NoSuchBeanDefinitionException(type);
318-
}
319-
if (existingBeans.length > 1) {
320-
existingBeans = new String[] {
321-
determinePrimaryCandidate(registry, existingBeans, type) };
322-
}
323-
registerSpy(definition, field, existingBeans[0]);
314+
registerSpy(definition, field,
315+
determineBeanName(existingBeans, definition, registry));
324316
}
325317
catch (RuntimeException ex) {
326318
throw new IllegalStateException(
327319
"Unable to register spy bean " + definition.getTypeToSpy(), ex);
328320
}
329321
}
330322

323+
private String determineBeanName(String[] existingBeans, SpyDefinition definition,
324+
BeanDefinitionRegistry registry) {
325+
if (StringUtils.hasText(definition.getName())) {
326+
return definition.getName();
327+
}
328+
if (existingBeans.length == 1) {
329+
return existingBeans[0];
330+
}
331+
return determinePrimaryCandidate(registry, existingBeans,
332+
definition.getTypeToSpy());
333+
}
334+
331335
private String determinePrimaryCandidate(BeanDefinitionRegistry registry,
332336
String[] candidateBeanNames, ResolvableType type) {
333337
String primaryBeanName = null;
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2016 the original author or authors.
2+
* Copyright 2012-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -33,12 +33,13 @@
3333
import static org.mockito.Mockito.verify;
3434

3535
/**
36-
* Test {@link SpyBean} on a test class field can be used to inject new spy instances.
36+
* Test {@link SpyBean} on a test class field can be used to inject a spy instance when
37+
* there are multiple candidates and one is primary.
3738
*
3839
* @author Phillip Webb
3940
*/
4041
@RunWith(SpringRunner.class)
41-
public class SpyBeanOnTestFieldForMultipleExistingBeansIntegrationTests {
42+
public class SpyBeanOnTestFieldForMultipleExistingBeansWithOnePrimaryIntegrationTests {
4243

4344
@SpyBean
4445
private SimpleExampleStringGenericService spy;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright 2012-2017 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.test.mock.mockito;
18+
19+
import org.junit.Test;
20+
import org.junit.runner.RunWith;
21+
import org.mockito.internal.util.MockUtil;
22+
23+
import org.springframework.boot.test.mock.mockito.example.SimpleExampleStringGenericService;
24+
import org.springframework.context.annotation.Bean;
25+
import org.springframework.context.annotation.Configuration;
26+
import org.springframework.test.context.junit4.SpringRunner;
27+
28+
import static org.assertj.core.api.Assertions.assertThat;
29+
30+
/**
31+
* Test {@link SpyBean} on a test class field can be used to inject a spy instance when
32+
* there are multiple candidates and one is chosen using the name attribute.
33+
*
34+
* @author Phillip Webb
35+
* @author Andy Wilkinson
36+
*/
37+
@RunWith(SpringRunner.class)
38+
public class SpyBeanWithNameOnTestFieldForMultipleExistingBeansTests {
39+
40+
@SpyBean(name = "two")
41+
private SimpleExampleStringGenericService spy;
42+
43+
@Test
44+
public void testSpying() throws Exception {
45+
assertThat(new MockUtil().isSpy(this.spy)).isTrue();
46+
assertThat(new MockUtil().getMockName(this.spy).toString()).isEqualTo("two");
47+
}
48+
49+
@Configuration
50+
static class Config {
51+
52+
@Bean
53+
public SimpleExampleStringGenericService one() {
54+
return new SimpleExampleStringGenericService("one");
55+
}
56+
57+
@Bean
58+
public SimpleExampleStringGenericService two() {
59+
return new SimpleExampleStringGenericService("two");
60+
}
61+
62+
}
63+
64+
}

0 commit comments

Comments
 (0)