commit
d1359220ed
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2021 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.
|
||||
|
|
@ -24,12 +24,14 @@ import javax.validation.Validator;
|
|||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfigurationTests.CustomValidatorConfiguration.TestBeanPostProcessor;
|
||||
import org.springframework.boot.test.util.TestPropertyValues;
|
||||
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.validation.beanvalidation.MethodValidationExcludeFilter;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
|
@ -55,171 +57,143 @@ import static org.mockito.Mockito.mock;
|
|||
*/
|
||||
class ValidationAutoConfigurationTests {
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
||||
@AfterEach
|
||||
void close() {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
}
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner(
|
||||
AnnotationConfigApplicationContext::new)
|
||||
.withConfiguration(AutoConfigurations.of(ValidationAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
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();
|
||||
this.contextRunner.run((context) -> {
|
||||
assertThat(context.getBeanNamesForType(Validator.class)).containsExactly("defaultValidator");
|
||||
assertThat(context.getBeanNamesForType(org.springframework.validation.Validator.class))
|
||||
.containsExactly("defaultValidator");
|
||||
assertThat(context.getBean(Validator.class)).isInstanceOf(LocalValidatorFactoryBean.class)
|
||||
.isEqualTo(context.getBean(org.springframework.validation.Validator.class));
|
||||
assertThat(isPrimaryBean(context, "defaultValidator")).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
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();
|
||||
this.contextRunner.withUserConfiguration(UserDefinedValidatorConfig.class).run((context) -> {
|
||||
assertThat(context.getBeanNamesForType(Validator.class)).containsExactly("customValidator");
|
||||
assertThat(context.getBeanNamesForType(org.springframework.validation.Validator.class))
|
||||
.containsExactly("customValidator");
|
||||
assertThat(context.getBean(Validator.class)).isInstanceOf(OptionalValidatorFactoryBean.class)
|
||||
.isEqualTo(context.getBean(org.springframework.validation.Validator.class));
|
||||
assertThat(isPrimaryBean(context, "customValidator")).isFalse();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
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();
|
||||
this.contextRunner.withUserConfiguration(UserDefinedDefaultValidatorConfig.class).run((context) -> {
|
||||
assertThat(context.getBeanNamesForType(Validator.class)).containsExactly("defaultValidator");
|
||||
assertThat(context.getBeanNamesForType(org.springframework.validation.Validator.class))
|
||||
.containsExactly("defaultValidator");
|
||||
assertThat(isPrimaryBean(context, "defaultValidator")).isFalse();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
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();
|
||||
this.contextRunner.withUserConfiguration(UserDefinedJsrValidatorConfig.class).run((context) -> {
|
||||
assertThat(context.getBeanNamesForType(Validator.class)).containsExactly("customValidator");
|
||||
assertThat(context.getBeanNamesForType(org.springframework.validation.Validator.class)).isEmpty();
|
||||
assertThat(isPrimaryBean(context, "customValidator")).isFalse();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
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();
|
||||
this.contextRunner.withUserConfiguration(UserDefinedSpringValidatorConfig.class).run((context) -> {
|
||||
assertThat(context.getBeanNamesForType(Validator.class)).containsExactly("defaultValidator");
|
||||
assertThat(context.getBeanNamesForType(org.springframework.validation.Validator.class))
|
||||
.containsExactly("customValidator", "anotherCustomValidator", "defaultValidator");
|
||||
assertThat(context.getBean(Validator.class)).isInstanceOf(LocalValidatorFactoryBean.class)
|
||||
.isEqualTo(context.getBean(org.springframework.validation.Validator.class));
|
||||
assertThat(isPrimaryBean(context, "defaultValidator")).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
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();
|
||||
this.contextRunner.withUserConfiguration(UserDefinedPrimarySpringValidatorConfig.class).run((context) -> {
|
||||
assertThat(context.getBeanNamesForType(Validator.class)).containsExactly("defaultValidator");
|
||||
assertThat(context.getBeanNamesForType(org.springframework.validation.Validator.class))
|
||||
.containsExactly("customValidator", "anotherCustomValidator", "defaultValidator");
|
||||
assertThat(context.getBean(Validator.class)).isInstanceOf(LocalValidatorFactoryBean.class);
|
||||
assertThat(context.getBean(org.springframework.validation.Validator.class))
|
||||
.isEqualTo(context.getBean("anotherCustomValidator"));
|
||||
assertThat(isPrimaryBean(context, "defaultValidator")).isFalse();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void validationIsEnabled() {
|
||||
load(SampleService.class);
|
||||
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1);
|
||||
SampleService service = this.context.getBean(SampleService.class);
|
||||
service.doSomething("Valid");
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(() -> service.doSomething("KO"));
|
||||
this.contextRunner.withUserConfiguration(SampleService.class).run((context) -> {
|
||||
assertThat(context.getBeansOfType(Validator.class)).hasSize(1);
|
||||
SampleService service = context.getBean(SampleService.class);
|
||||
service.doSomething("Valid");
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(() -> service.doSomething("KO"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void classCanBeExcludedFromValidation() {
|
||||
load(ExcludedServiceConfiguration.class);
|
||||
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1);
|
||||
ExcludedService service = this.context.getBean(ExcludedService.class);
|
||||
service.doSomething("Valid");
|
||||
assertThatNoException().isThrownBy(() -> service.doSomething("KO"));
|
||||
this.contextRunner.withUserConfiguration(ExcludedServiceConfiguration.class).run((context) -> {
|
||||
assertThat(context.getBeansOfType(Validator.class)).hasSize(1);
|
||||
ExcludedService service = context.getBean(ExcludedService.class);
|
||||
service.doSomething("Valid");
|
||||
assertThatNoException().isThrownBy(() -> service.doSomething("KO"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void validationUsesCglibProxy() {
|
||||
load(DefaultAnotherSampleService.class);
|
||||
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1);
|
||||
DefaultAnotherSampleService service = this.context.getBean(DefaultAnotherSampleService.class);
|
||||
service.doSomething(42);
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(() -> service.doSomething(2));
|
||||
this.contextRunner.withUserConfiguration(DefaultAnotherSampleService.class).run((context) -> {
|
||||
assertThat(context.getBeansOfType(Validator.class)).hasSize(1);
|
||||
DefaultAnotherSampleService service = context.getBean(DefaultAnotherSampleService.class);
|
||||
service.doSomething(42);
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(() -> service.doSomething(2));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void validationCanBeConfiguredToUseJdkProxy() {
|
||||
load(AnotherSampleServiceConfiguration.class, "spring.aop.proxy-target-class=false");
|
||||
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1);
|
||||
assertThat(this.context.getBeansOfType(DefaultAnotherSampleService.class)).isEmpty();
|
||||
AnotherSampleService service = this.context.getBean(AnotherSampleService.class);
|
||||
service.doSomething(42);
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(() -> service.doSomething(2));
|
||||
this.contextRunner.withUserConfiguration(AnotherSampleServiceConfiguration.class)
|
||||
.withPropertyValues("spring.aop.proxy-target-class=false").run((context) -> {
|
||||
assertThat(context.getBeansOfType(Validator.class)).hasSize(1);
|
||||
assertThat(context.getBeansOfType(DefaultAnotherSampleService.class)).isEmpty();
|
||||
AnotherSampleService service = context.getBean(AnotherSampleService.class);
|
||||
service.doSomething(42);
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.isThrownBy(() -> service.doSomething(2));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void userDefinedMethodValidationPostProcessorTakesPrecedence() {
|
||||
load(SampleConfiguration.class);
|
||||
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1);
|
||||
Object userMethodValidationPostProcessor = this.context.getBean("testMethodValidationPostProcessor");
|
||||
assertThat(this.context.getBean(MethodValidationPostProcessor.class))
|
||||
.isSameAs(userMethodValidationPostProcessor);
|
||||
assertThat(this.context.getBeansOfType(MethodValidationPostProcessor.class)).hasSize(1);
|
||||
assertThat(this.context.getBean(Validator.class))
|
||||
.isNotSameAs(ReflectionTestUtils.getField(userMethodValidationPostProcessor, "validator"));
|
||||
this.contextRunner.withUserConfiguration(SampleConfiguration.class).run((context) -> {
|
||||
assertThat(context.getBeansOfType(Validator.class)).hasSize(1);
|
||||
Object userMethodValidationPostProcessor = context.getBean("testMethodValidationPostProcessor");
|
||||
assertThat(context.getBean(MethodValidationPostProcessor.class))
|
||||
.isSameAs(userMethodValidationPostProcessor);
|
||||
assertThat(context.getBeansOfType(MethodValidationPostProcessor.class)).hasSize(1);
|
||||
assertThat(context.getBean(Validator.class))
|
||||
.isNotSameAs(ReflectionTestUtils.getField(userMethodValidationPostProcessor, "validator"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void methodValidationPostProcessorValidatorDependencyDoesNotTriggerEarlyInitialization() {
|
||||
load(CustomValidatorConfiguration.class);
|
||||
assertThat(this.context.getBean(TestBeanPostProcessor.class).postProcessed).contains("someService");
|
||||
this.contextRunner.withUserConfiguration(CustomValidatorConfiguration.class)
|
||||
.run((context) -> assertThat(context.getBean(TestBeanPostProcessor.class).postProcessed)
|
||||
.contains("someService"));
|
||||
}
|
||||
|
||||
private boolean isPrimaryBean(String beanName) {
|
||||
return this.context.getBeanDefinition(beanName).isPrimary();
|
||||
}
|
||||
|
||||
private void load(Class<?> config, String... environment) {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
TestPropertyValues.of(environment).applyTo(ctx);
|
||||
if (config != null) {
|
||||
ctx.register(config);
|
||||
}
|
||||
ctx.register(ValidationAutoConfiguration.class);
|
||||
ctx.refresh();
|
||||
this.context = ctx;
|
||||
private boolean isPrimaryBean(AssertableApplicationContext context, String beanName) {
|
||||
return ((BeanDefinitionRegistry) context.getSourceApplicationContext()).getBeanDefinition(beanName).isPrimary();
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
|
|
|
|||
Loading…
Reference in New Issue