Refine validator and MVC validator configuration

This commit ensures that a primary JSR 303 and Spring Validator will be
exposed if the auto-configuration kicks in. As `LocalValidatorFactoryBean`
exposes 3 contracts (JSR-303 `Validator` and `ValidatorFactory` as well as
the `Spring` validator one), this makes sure that those types can be
injected by type.

`LocalValidatorFactoryBean` exposes 3 contracts and we're only checking
for the absence of a `javax.validation.Validator` to auto-configure a
`LocalValidatorFactoryBean`. If no standard JSR validator exists but a
Spring's `Validator` exists and is primary, we shouldn't flag the
auto-configured one as `@Primary`. Previous iterations on this feature
have made sure that we'll auto-configure at most one
`javax.validation.Validator` so not flagging it `@Primary` is no problem.

This commit also restores and adds tests that validates
`ValidationAutoConfiguration` will configure a JSR validator even if a
Spring Validator is present.

This effectively fixes gh-8495 in a different way.

Closes gh-8979
Closes gh-8976
pull/9065/head
Stephane Nicoll 8 years ago
parent f42998f5ca
commit 1de2316a0b

@ -0,0 +1,88 @@
/*
* 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.autoconfigure.validation;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
/**
* Enable the {@code Primary} flag on the auto-configured validator if necessary.
* <p>
* As {@link LocalValidatorFactoryBean} exposes 3 validator related contracts and we're
* only checking for the absence {@link javax.validation.Validator}, we should flag the
* auto-configured validator as primary only if no Spring's {@link Validator} is flagged
* as primary.
*
* @author Stephane Nicoll
*/
class PrimaryDefaultValidatorPostProcessor
implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
/**
* The bean name of the auto-configured Validator.
*/
private static final String VALIDATOR_BEAN_NAME = "defaultValidator";
private ConfigurableListableBeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
if (beanFactory instanceof ConfigurableListableBeanFactory) {
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
}
}
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
if (this.beanFactory == null) {
return;
}
if (!registry.containsBeanDefinition(VALIDATOR_BEAN_NAME)) {
return;
}
BeanDefinition def = registry.getBeanDefinition(VALIDATOR_BEAN_NAME);
if (def != null
&& this.beanFactory.isTypeMatch(VALIDATOR_BEAN_NAME, LocalValidatorFactoryBean.class)
&& def.getRole() == BeanDefinition.ROLE_INFRASTRUCTURE) {
def.setPrimary(!hasPrimarySpringValidator(registry));
}
}
private boolean hasPrimarySpringValidator(BeanDefinitionRegistry registry) {
String[] validatorBeans = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Validator.class, false, false);
for (String validatorBean : validatorBeans) {
BeanDefinition def = registry.getBeanDefinition(validatorBean);
if (def != null && def.isPrimary()) {
return true;
}
}
return false;
}
}

@ -28,6 +28,7 @@ import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.validation.MessageInterpolatorFactory; import org.springframework.boot.validation.MessageInterpolatorFactory;
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.Import;
import org.springframework.context.annotation.Role; import org.springframework.context.annotation.Role;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
@ -43,12 +44,13 @@ import org.springframework.validation.beanvalidation.MethodValidationPostProcess
@Configuration @Configuration
@ConditionalOnClass(ExecutableValidator.class) @ConditionalOnClass(ExecutableValidator.class)
@ConditionalOnResource(resources = "classpath:META-INF/services/javax.validation.spi.ValidationProvider") @ConditionalOnResource(resources = "classpath:META-INF/services/javax.validation.spi.ValidationProvider")
@Import(PrimaryDefaultValidatorPostProcessor.class)
public class ValidationAutoConfiguration { public class ValidationAutoConfiguration {
@Bean @Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE) @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@ConditionalOnMissingBean @ConditionalOnMissingBean(Validator.class)
public static Validator jsr303Validator() { public static LocalValidatorFactoryBean defaultValidator() {
LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean(); LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
MessageInterpolatorFactory interpolatorFactory = new MessageInterpolatorFactory(); MessageInterpolatorFactory interpolatorFactory = new MessageInterpolatorFactory();
factoryBean.setMessageInterpolator(interpolatorFactory.getObject()); factoryBean.setMessageInterpolator(interpolatorFactory.getObject());

@ -31,15 +31,20 @@ import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; 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.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor; import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
import org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
/** /**
* Tests for {@link ValidationAutoConfiguration}. * Tests for {@link ValidationAutoConfiguration}.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Phillip Webb
*/ */
public class ValidationAutoConfigurationTests { public class ValidationAutoConfigurationTests {
@ -55,6 +60,95 @@ public class ValidationAutoConfigurationTests {
} }
} }
@Test
public void validationAutoConfigurationShouldConfigureDefaultValidator() {
load(Config.class);
String[] jsrValidatorNames = this.context.getBeanNamesForType(Validator.class);
String[] springValidatorNames = this.context
.getBeanNamesForType(org.springframework.validation.Validator.class);
assertThat(jsrValidatorNames).containsExactly("defaultValidator");
assertThat(springValidatorNames).containsExactly("defaultValidator");
Validator jsrValidator = this.context.getBean(Validator.class);
org.springframework.validation.Validator springValidator = this.context
.getBean(org.springframework.validation.Validator.class);
assertThat(jsrValidator).isInstanceOf(LocalValidatorFactoryBean.class);
assertThat(jsrValidator).isEqualTo(springValidator);
assertThat(isPrimaryBean("defaultValidator")).isTrue();
}
@Test
public void validationAutoConfigurationWhenUserProvidesValidatorShouldBackOff() {
load(UserDefinedValidatorConfig.class);
String[] jsrValidatorNames = this.context.getBeanNamesForType(Validator.class);
String[] springValidatorNames = this.context
.getBeanNamesForType(org.springframework.validation.Validator.class);
assertThat(jsrValidatorNames).containsExactly("customValidator");
assertThat(springValidatorNames).containsExactly("customValidator");
org.springframework.validation.Validator springValidator = this.context
.getBean(org.springframework.validation.Validator.class);
Validator jsrValidator = this.context.getBean(Validator.class);
assertThat(jsrValidator).isInstanceOf(OptionalValidatorFactoryBean.class);
assertThat(jsrValidator).isEqualTo(springValidator);
assertThat(isPrimaryBean("customValidator")).isFalse();
}
@Test
public void validationAutoConfigurationWhenUserProvidesDefaultValidatorShouldNotEnablePrimary() {
load(UserDefinedDefaultValidatorConfig.class);
String[] jsrValidatorNames = this.context.getBeanNamesForType(Validator.class);
String[] springValidatorNames = this.context
.getBeanNamesForType(org.springframework.validation.Validator.class);
assertThat(jsrValidatorNames).containsExactly("defaultValidator");
assertThat(springValidatorNames).containsExactly("defaultValidator");
assertThat(isPrimaryBean("defaultValidator")).isFalse();
}
@Test
public void validationAutoConfigurationWhenUserProvidesJsrValidatorShouldBackOff() {
load(UserDefinedJsrValidatorConfig.class);
String[] jsrValidatorNames = this.context.getBeanNamesForType(Validator.class);
String[] springValidatorNames = this.context
.getBeanNamesForType(org.springframework.validation.Validator.class);
assertThat(jsrValidatorNames).containsExactly("customValidator");
assertThat(springValidatorNames).isEmpty();
assertThat(isPrimaryBean("customValidator")).isFalse();
}
@Test
public void validationAutoConfigurationWhenUserProvidesSpringValidatorShouldCreateJsrValidator() {
load(UserDefinedSpringValidatorConfig.class);
String[] jsrValidatorNames = this.context.getBeanNamesForType(Validator.class);
String[] springValidatorNames = this.context
.getBeanNamesForType(org.springframework.validation.Validator.class);
assertThat(jsrValidatorNames).containsExactly("defaultValidator");
assertThat(springValidatorNames).containsExactly(
"customValidator", "anotherCustomValidator", "defaultValidator");
Validator jsrValidator = this.context.getBean(Validator.class);
org.springframework.validation.Validator springValidator = this.context
.getBean(org.springframework.validation.Validator.class);
assertThat(jsrValidator).isInstanceOf(LocalValidatorFactoryBean.class);
assertThat(jsrValidator).isEqualTo(springValidator);
assertThat(isPrimaryBean("defaultValidator")).isTrue();
}
@Test
public void validationAutoConfigurationWhenUserProvidesPrimarySpringValidatorShouldRemovePrimaryFlag() {
load(UserDefinedPrimarySpringValidatorConfig.class);
String[] jsrValidatorNames = this.context.getBeanNamesForType(Validator.class);
String[] springValidatorNames = this.context
.getBeanNamesForType(org.springframework.validation.Validator.class);
assertThat(jsrValidatorNames).containsExactly("defaultValidator");
assertThat(springValidatorNames).containsExactly(
"customValidator", "anotherCustomValidator", "defaultValidator");
Validator jsrValidator = this.context.getBean(Validator.class);
org.springframework.validation.Validator springValidator = this.context
.getBean(org.springframework.validation.Validator.class);
assertThat(jsrValidator).isInstanceOf(LocalValidatorFactoryBean.class);
assertThat(springValidator).isEqualTo(
this.context.getBean("anotherCustomValidator"));
assertThat(isPrimaryBean("defaultValidator")).isFalse();
}
@Test @Test
public void validationIsEnabled() { public void validationIsEnabled() {
load(SampleService.class); load(SampleService.class);
@ -104,7 +198,11 @@ public class ValidationAutoConfigurationTests {
.getPropertyValue("validator")); .getPropertyValue("validator"));
} }
public void load(Class<?> config, String... environment) { private boolean isPrimaryBean(String beanName) {
return this.context.getBeanDefinition(beanName).isPrimary();
}
private void load(Class<?> config, String... environment) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(ctx, environment); EnvironmentTestUtils.addEnvironment(ctx, environment);
if (config != null) { if (config != null) {
@ -115,6 +213,72 @@ public class ValidationAutoConfigurationTests {
this.context = ctx; this.context = ctx;
} }
@Configuration
static class Config {
}
@Configuration
static class UserDefinedValidatorConfig {
@Bean
public OptionalValidatorFactoryBean customValidator() {
return new OptionalValidatorFactoryBean();
}
}
@Configuration
static class UserDefinedDefaultValidatorConfig {
@Bean
public OptionalValidatorFactoryBean defaultValidator() {
return new OptionalValidatorFactoryBean();
}
}
@Configuration
static class UserDefinedJsrValidatorConfig {
@Bean
public Validator customValidator() {
return mock(Validator.class);
}
}
@Configuration
static class UserDefinedSpringValidatorConfig {
@Bean
public org.springframework.validation.Validator customValidator() {
return mock(org.springframework.validation.Validator.class);
}
@Bean
public org.springframework.validation.Validator anotherCustomValidator() {
return mock(org.springframework.validation.Validator.class);
}
}
@Configuration
static class UserDefinedPrimarySpringValidatorConfig {
@Bean
public org.springframework.validation.Validator customValidator() {
return mock(org.springframework.validation.Validator.class);
}
@Bean
@Primary
public org.springframework.validation.Validator anotherCustomValidator() {
return mock(org.springframework.validation.Validator.class);
}
}
@Validated @Validated
static class SampleService { static class SampleService {

@ -39,6 +39,7 @@ import org.junit.rules.ExpectedException;
import org.springframework.beans.DirectFieldAccessor; import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter; import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter;
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration.WelcomePageHandlerMapping; import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration.WelcomePageHandlerMapping;
import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext; import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext;
@ -59,6 +60,7 @@ import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.validation.Validator; import org.springframework.validation.Validator;
@ -655,77 +657,126 @@ public class WebMvcAutoConfigurationTests {
} }
@Test @Test
public void validationNoJsr303ValidatorExposedByDefault() { public void validatorWhenNoValidatorShouldUseDefault() {
load(); load(null, new Class<?>[] { ValidationAutoConfiguration.class });
assertThat(this.context.getBeansOfType(ValidatorFactory.class)).isEmpty(); assertThat(this.context.getBeansOfType(ValidatorFactory.class)).isEmpty();
assertThat(this.context.getBeansOfType(javax.validation.Validator.class)) assertThat(this.context.getBeansOfType(javax.validation.Validator.class))
.isEmpty(); .isEmpty();
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1); String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
assertThat(springValidatorBeans).containsExactly("mvcValidator");
} }
@Test @Test
public void validationCustomConfigurerTakesPrecedence() { public void validatorWhenNoCustomizationShouldUseAutoConfigured() {
load(MvcValidator.class); load();
String[] jsrValidatorBeans = this.context
.getBeanNamesForType(javax.validation.Validator.class);
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
assertThat(jsrValidatorBeans).containsExactly("defaultValidator");
assertThat(springValidatorBeans).containsExactly("defaultValidator", "mvcValidator");
Validator validator = this.context.getBean("mvcValidator", Validator.class);
assertThat(validator).isInstanceOf(WebMvcValidator.class);
Object defaultValidator = this.context.getBean("defaultValidator");
assertThat(((WebMvcValidator) validator).getTarget()).isSameAs(defaultValidator);
// Primary Spring validator is the one use by MVC behind the scenes
assertThat(this.context.getBean(Validator.class)).isEqualTo(defaultValidator);
}
@Test
public void validatorWithConfigurerShouldUseSpringValidator() {
load(MvcValidator.class, new Class<?>[] { ValidationAutoConfiguration.class });
assertThat(this.context.getBeansOfType(ValidatorFactory.class)).isEmpty(); assertThat(this.context.getBeansOfType(ValidatorFactory.class)).isEmpty();
assertThat(this.context.getBeansOfType(javax.validation.Validator.class)) assertThat(this.context.getBeansOfType(javax.validation.Validator.class))
.isEmpty(); .isEmpty();
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1); String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
Validator validator = this.context.getBean(Validator.class); assertThat(springValidatorBeans).containsExactly("mvcValidator");
assertThat(validator) assertThat(this.context.getBean("mvcValidator"))
.isSameAs(this.context.getBean(MvcValidator.class).validator); .isSameAs(this.context.getBean(MvcValidator.class).validator);
} }
@Test @Test
public void validationCustomConfigurerTakesPrecedenceAndDoNotExposeJsr303() { public void validatorWithConfigurerDoesNotExposeJsr303() {
load(MvcJsr303Validator.class); load(MvcJsr303Validator.class, new Class<?>[] { ValidationAutoConfiguration.class });
assertThat(this.context.getBeansOfType(ValidatorFactory.class)).isEmpty(); assertThat(this.context.getBeansOfType(ValidatorFactory.class)).isEmpty();
assertThat(this.context.getBeansOfType(javax.validation.Validator.class)) assertThat(this.context.getBeansOfType(javax.validation.Validator.class))
.isEmpty(); .isEmpty();
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1); String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
Validator validator = this.context.getBean(Validator.class); assertThat(springValidatorBeans).containsExactly("mvcValidator");
Validator validator = this.context.getBean("mvcValidator", Validator.class);
assertThat(validator).isInstanceOf(WebMvcValidator.class); assertThat(validator).isInstanceOf(WebMvcValidator.class);
assertThat(((WebMvcValidator) validator).getTarget()) assertThat(((WebMvcValidator) validator).getTarget())
.isSameAs(this.context.getBean(MvcJsr303Validator.class).validator); .isSameAs(this.context.getBean(MvcJsr303Validator.class).validator);
} }
@Test @Test
public void validationJsr303CustomValidatorReusedAsSpringValidator() { public void validatorWithConfigurerTakesPrecedence() {
load(CustomValidator.class); load(MvcValidator.class);
assertThat(this.context.getBeansOfType(ValidatorFactory.class)).hasSize(1); assertThat(this.context.getBeansOfType(ValidatorFactory.class)).hasSize(1);
assertThat(this.context.getBeansOfType(javax.validation.Validator.class)) assertThat(this.context.getBeansOfType(javax.validation.Validator.class))
.hasSize(1); .hasSize(1);
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(2); String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
assertThat(springValidatorBeans).containsExactly("defaultValidator", "mvcValidator");
assertThat(this.context.getBean("mvcValidator"))
.isSameAs(this.context.getBean(MvcValidator.class).validator);
// Primary Spring validator is the auto-configured one as the MVC one has been
// customized via a WebMvcConfigurer
assertThat(this.context.getBean(Validator.class))
.isEqualTo(this.context.getBean("defaultValidator"));
}
@Test
public void validatorWithCustomSpringValidatorIgnored() {
load(CustomSpringValidator.class);
String[] jsrValidatorBeans = this.context
.getBeanNamesForType(javax.validation.Validator.class);
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
assertThat(jsrValidatorBeans).containsExactly("defaultValidator");
assertThat(springValidatorBeans).containsExactly(
"customSpringValidator", "defaultValidator", "mvcValidator");
Validator validator = this.context.getBean("mvcValidator", Validator.class); Validator validator = this.context.getBean("mvcValidator", Validator.class);
assertThat(validator).isInstanceOf(WebMvcValidator.class); assertThat(validator).isInstanceOf(WebMvcValidator.class);
Object defaultValidator = this.context.getBean("defaultValidator");
assertThat(((WebMvcValidator) validator).getTarget()) assertThat(((WebMvcValidator) validator).getTarget())
.isSameAs(this.context.getBean(javax.validation.Validator.class)); .isSameAs(defaultValidator);
// Primary Spring validator is the one use by MVC behind the scenes
assertThat(this.context.getBean(Validator.class)).isEqualTo(defaultValidator);
} }
@Test @Test
public void validationJsr303ValidatorExposedAsSpringValidator() { public void validatorWithCustomJsr303ValidatorExposedAsSpringValidator() {
load(Jsr303Validator.class); load(CustomJsr303Validator.class);
assertThat(this.context.getBeansOfType(ValidatorFactory.class)).isEmpty(); assertThat(this.context.getBeansOfType(ValidatorFactory.class)).isEmpty();
assertThat(this.context.getBeansOfType(javax.validation.Validator.class)) String[] jsrValidatorBeans = this.context
.hasSize(1); .getBeanNamesForType(javax.validation.Validator.class);
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1); String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
assertThat(jsrValidatorBeans).containsExactly("customJsr303Validator");
assertThat(springValidatorBeans).containsExactly("mvcValidator");
Validator validator = this.context.getBean(Validator.class); Validator validator = this.context.getBean(Validator.class);
assertThat(validator).isInstanceOf(WebMvcValidator.class); assertThat(validator).isInstanceOf(WebMvcValidator.class);
SpringValidatorAdapter target = ((WebMvcValidator) validator) SpringValidatorAdapter target = ((WebMvcValidator) validator)
.getTarget(); .getTarget();
assertThat(new DirectFieldAccessor(target).getPropertyValue("targetValidator")) assertThat(new DirectFieldAccessor(target).getPropertyValue("targetValidator"))
.isSameAs(this.context.getBean(javax.validation.Validator.class)); .isSameAs(this.context.getBean("customJsr303Validator"));
} }
private void load(Class<?> config, String... environment) { private void load(Class<?> config, String... environment) {
load(config, null, environment);
}
private void load(Class<?> config, Class<?>[] exclude, String... environment) {
this.context = new AnnotationConfigEmbeddedWebApplicationContext(); this.context = new AnnotationConfigEmbeddedWebApplicationContext();
EnvironmentTestUtils.addEnvironment(this.context, environment); EnvironmentTestUtils.addEnvironment(this.context, environment);
List<Class<?>> configClasses = new ArrayList<Class<?>>(); List<Class<?>> configClasses = new ArrayList<Class<?>>();
if (config != null) { if (config != null) {
configClasses.add(config); configClasses.add(config);
} }
configClasses.addAll(Arrays.asList(Config.class, WebMvcAutoConfiguration.class, configClasses.addAll(Arrays.asList(Config.class,
ValidationAutoConfiguration.class, WebMvcAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class)); PropertyPlaceholderAutoConfiguration.class));
if (!ObjectUtils.isEmpty(exclude)) {
configClasses.removeAll(Arrays.asList(exclude));
}
this.context.register(configClasses.toArray(new Class<?>[configClasses.size()])); this.context.register(configClasses.toArray(new Class<?>[configClasses.size()]));
this.context.refresh(); this.context.refresh();
} }
@ -919,21 +970,21 @@ public class WebMvcAutoConfigurationTests {
} }
@Configuration @Configuration
static class Jsr303Validator { static class CustomJsr303Validator {
@Bean @Bean
public javax.validation.Validator jsr303Validator() { public javax.validation.Validator customJsr303Validator() {
return mock(javax.validation.Validator.class); return mock(javax.validation.Validator.class);
} }
} }
@Configuration @Configuration
static class CustomValidator { static class CustomSpringValidator {
@Bean @Bean
public Validator customValidator() { public Validator customSpringValidator() {
return new LocalValidatorFactoryBean(); return mock(Validator.class);
} }
} }

Loading…
Cancel
Save