From 7d632ea3974f438d08444ba11cf16fc161c9dcd8 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 1 Apr 2021 10:00:46 +0100 Subject: [PATCH] Use ApplicationContextRunner in ValidationAutoConfigurationTests Closes gh-25859 --- .../ValidationAutoConfigurationTests.java | 201 ++++++++---------- 1 file changed, 87 insertions(+), 114 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/validation/ValidationAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/validation/ValidationAutoConfigurationTests.java index fcc05056b4..35df630d12 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/validation/ValidationAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/validation/ValidationAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 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.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -53,162 +55,133 @@ 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 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)