1.概述
在我们之前的指南中@configurationProperties.那我们学会了如何设置和使用@configurationProperties.带有弹簧启动的注释,用于使用外部配置。
在本教程中,我们将展示如何测试依赖于的配置类@configurationProperties.注解确保我们的配置数据被正确加载并绑定到它们对应的字段。
2.依赖性
在我们的Maven项目中,将使用春战启动和spring-boot-starter-test启用核心spring API和spring的测试API,分别是:
<父> < groupId > org.springframework。 2.4.1 >org.springframework。 test . start -boot-start -test test . start -boot-start -test
此外,让我们使用我们的项目bean验证依赖关系因为我们将在后面使用它们:
< !——JSR-380 bean验证——> <依赖> org。hibernate-validator el < / groupId > < artifactId > javax。 3.0.0 web < / groupId > < artifactId > javax。2.2.6 el < / artifactId > <版本>。< /版本> < / >的依赖
3.属性绑定到用户定义的pojos
当使用外部化配置时,我们通常创建包含与匹配配置属性对应的字段的POJO。正如我们已经知道的那样,Spring将自动将配置属性绑定到我们创建的Java类中。
首先,让我们假设在将要调用的属性文件中有一些服务器配置src / test / compresence / server-config-test.properties:
server.address.ip server.resources_path.imgs = = 192.168.0.1 /根/一个
现在,让我们定义一个简单的配置类对应于前面的属性文件:
@configuration @configurationProperties(prefix =“server”)公共类serverconfig {私有地址地址;私有地图<字符串,字符串> resourcespath;// getters和setter}
以及相应的地址类型:
public class Address {private String ip;// getters和setter}
最后,让我们注入serverconfig.将POJO放入我们的测试类中,并验证它的所有字段都被正确设置:
@ExtendWith(SpringExtension.class) @EnableConfigurationProperties(value = ServerConfig.class) @TestPropertySource("classpath:server-config-test.properties") public class BindingPropertiesToUserDefinedPOJOUnitTest {@Autowired private ServerConfig ServerConfig;@Test void givenUserDefinedPOJO_whenBindingPropertiesFile_thenAllFieldsAreSet() {assertEquals(“192.168.0.1”,serverConfig.getAddress().getIp()));Map expectedResourcesPath = new HashMap<>();expectedResourcesPath。(“一个”、“/根/一个”);assertequal (expectedResourcesPath serverConfig.getResourcesPath ());}}
在此测试中,我们使用以下注释:
- @extendwith.- 将Spring的TestContext框架与JUNIT5集成
- @enableconfigurationProperties.-支持@configurationProperties.bean(在本例中为serverconfig.豆)
- @testpropertysource.-指定覆盖默认值的测试文件application.properties.文件
4.@configurationProperties.在@ bean方法
创建配置bean的另一种方式是使用@configurationProperties.注释在@ bean方法。
例如getDefaultConfigs ()方法创建A.serverconfig.配置bean:
@configuration公共类serverconfigfactory {@bean(name =“default_bean”)@configurationproperties(prefix =“server.default”)public serverconfig getDefaultConfigs(){return new serverconfig();}}
如我们所见,我们能够配置serverconfig.实例使用@configurationProperties.在getDefaultConfigs ()方法,而不必编辑serverconfig.班级本身。这在使用限制访问的外部第三方类时特别有用。
接下来,让我们定义一个示例外部属性:
server.default.address.ip = 192.168.0.2
最后,告诉春天使用serverconfigfactory.加载时的课程ApplicationContext.(因此,创建配置bean),我们将添加@ContextConfiguration注释到测试类:
@ExtendWith (SpringExtension.class) @EnableConfigurationProperties(值= ServerConfig.class) @ContextConfiguration(类= ServerConfigFactory.class) @TestPropertySource(“类路径:server-config-test.properties”)公开课BindingPropertiesToBeanMethodsUnitTest {@ autowired @ qualifier (default_bean)私人ServerConfig ServerConfig;@Test void givenBeanAnnotatedMethod_whenBindingProperties_thenAllFieldsAreSet() {assertEquals(“192.168.0.2”,serverConfig.getAddress().getIp()));/ /其他断言…}}
5.属性验证
要启用豆验证在春天,我们必须向顶级课程注释@Validated.。然后,我们添加所需的javax.validation约束:
@Configuration @ConfigurationProperties(prefix = "validate") @Validated public class MailServer {@NotNull @NotEmpty private Map propertiesMap;@Valid private MailConfig MailConfig = new MailConfig();// getters和setter}
同样,MailConfig类也有一些约束:
public class MailConfig {@NotBlank @Email private String address;// getters和setter}
通过提供有效的数据集:
validate.propertiesMap。第一次= prop1 validate.propertiesMap.second = prop2(电子邮件保护)
应用程序将正常启动,我们的单元测试将通过:
@ExtendWith(SpringExtension.class) @EnableConfigurationProperties(value = MailServer.class) @TestPropertySource("classpath:property-validation-test.properties") public class PropertyValidationUnitTest {@Autowired private MailServer MailServer;私有静态验证器propertyValidator;@BeforeAll public static void setup() {propertyValidator = validator . builddefaultvalidatorfactory ().getValidator();} @Test void whenBindingPropertiesToValidatedBeans_thenConstrainsAreChecked() {assertEquals(0, propertyValidator.validate(mailServer.getPropertiesMap()).size());assertequal (0, propertyValidator.validate (mailServer.getMailConfig ()) .size ());}}
另一方面,如果我们使用无效的属性,Spring将抛出IllegalStateException.在启动。
例如,使用以下任何一种无效配置:
validate.propertiesmap.second = validate.mail_config.address = user1.test
将导致我们的应用程序失败,错误信息如下:
属性:validate.propertiesmap [第二]值:原因:不得是空白的:validate.mailconfig.address值:user1.test原因:必须是一块良好的电子邮件地址
请注意,我们使用@Valid在mailConfig字段,以确保MailConfig约束被检查,即使validate.mailConfig.address没有定义。否则,Spring将设置mailConfig至零并正常启动应用程序。
6.属性转换
Spring Boot属性转换使我们能够将某些属性转换为特定类型。
在本节中,我们将首先测试使用Spring的内置转换的配置类。然后,我们将测试我们创建自己的自定义转换器。
6.1。Spring Boot的默认转换
让我们考虑以下数据大小和持续时间属性:
#数据大小convert.upload_speed = 500MB Convert.Download_Speed = 10#持续Convert.backup_day = 1d convert.backup_hour = 8
Spring Boot将自动将这些属性绑定到匹配数据化和期间领域中定义的PropertyConversion配置类:
@configuration @configurationProperties(prefix =“convert”)公共类属性conversion {private datasize uploadspeed;@DataSizeUnit(DataUnit.Gigabytes)私有数据数据DownloadSpeed;私人持续时间返回;@durationUnit(chronounit.hours)私人持续时间背景;// getters和setter}
现在,让我们检查转换结果:
@ExtendWith (SpringExtension.class) @EnableConfigurationProperties(值= PropertyConversion.class) @ContextConfiguration(类= CustomCredentialsConverter.class) @TestPropertySource(“类路径:spring-conversion-test.properties”)公开课SpringPropertiesConversionUnitTest {@ autowired私人PropertyConversion PropertyConversion;@Test void whenUsingSpringDefaultSizeConversion_thenDataSizeObjectIsSet() {assertEquals(DataSize.ofMegabytes(500), propertyConversion.getUploadSpeed());assertequal (DataSize.ofGigabytes (10), propertyConversion.getDownloadSpeed ());} @Test void whenusingspringdefaultdurationconversion_theendurationobjectisset () {assertEquals(Duration.ofDays(1), propertyConversion.getBackupDay());assertequal (Duration.ofHours (8), propertyConversion.getBackupHour ());}}
6.2。自定义转换器
现在假设我们要转换convert.credentials.属性:
convert.credentials =用户,123
进入以下内容凭据类:
公共类凭据{私有字符串用户名;私有字符串密码;// getters和setter}
为此,我们可以实现自定义转换器:
@Component @ConfigurationPropertiesBinding public class CustomCredentialsConverter实现Converter {@Override public Credentials convert(String source) {String[] data = source.split(",");返回新的凭据(数据[0],数据[1]);}}
最后,我们加上a证书现场到PropertyConversion类:
public class PropertyConversion{私有凭证凭证;/ /……}
在我们的springpropertiesconversion unittest.测试类,我们还需要添加@ContextConfiguration在Spring上下文中注册自定义转换器:
@ContextConfiguration(classes=CustomCredentialsConverter.class) public class SpringPropertiesConversionUnitTest{//…@Test void whenRegisteringCustomCredentialsConverter_thenCredentialsAreParsed() {assertEquals(“用户”,propertyConversion.getCredentials().getUsername());.getPassword assertequal(“123”,propertyConversion.getCredentials () ());}}
正如前面的断言所示,Spring使用了我们的自定义转换器来解析convert.credentials.房子变成一个证书实例。
7.YAML文件绑定
用于分层配置数据,YAML的配置可能更方便。此外,yaml支持在同一文档中定义多个配置文件。
以下application.yml坐落在src /测试/资源/的“测试”配置文件serverconfig.类:
Spring:Config:Activate:On-Profile:测试服务器:地址:IP:IP:192.168.0.4 Resources_Path:IMGS:/ etc / test / imgs ---#其他配置文件
结果,以下测试将通过:
@extendwith(springextension.class)@contextconfiguration(initializers = configDateApplicationContextinitializer.class)@enableConfigurationProperties(value = serverconfig.class)@activeprofiles(“test”)公共类绑定ymlpropertiesunittest {@autowired private serverconfig serverconfig;@test void whitbindingymlconfigfile_thenallfieldsareset(){assertequals(“192.168.0.4”,serverconfig.getAddress()。getIP());//其他断言......}}
关于所使用的注释,有几个注释:
- @ContextConfiguration(初始值设定项= ConfigDataApplicationContextInitializer.class)- 加载application.yml文件
- @ActiveProfiles(“测试”)-指定在此测试期间将使用“测试”配置文件
最后,让我们记住既不@ProperySource.也不@TestProperySource支持加载.yml文件。因此,我们应该始终将您的YAML配置置于其中application.yml文件。
8.压倒一切的@configurationProperties.配置
有时候,我们可能想要覆盖配置属性装入的@configurationProperties.使用另一个数据集,特别是在测试时。
正如我们在前面的例子中所展示的,我们可以使用@TestPropertySource(“path_to_new_data_set”)替换整个原始配置(下/ src / main /资源)用一个新的。
或者,我们可以使用该选择性地替换一些原始属性属性属性@testpropertysource.还有。
假设我们想重写前面定义的validate.mail_config.address属性具有另一个值。我们所要做的就是为我们的测试类添加注释@testpropertysource.然后通过通过该项目为同一属性分配新值属性列表:
@TestPropertySource(属性= {"(电子邮件保护)"})
因此,Spring将使用新定义的值:
assertequal(“(电子邮件保护)“,mailserver.getmailconfig()。getaddress());
9.结论
在本教程中,我们看到了如何测试使用@configurationProperties.注释来加载。特性和.yml配置文件。
像往常一样,本文的源代码是可用的在GitHub。