junit 如何测试从yaml阅读的外部化配置

hl0ma9xz  于 2022-11-11  发布在  其他
关注(0)|答案(2)|浏览(166)

这是我第一次使用外部化配置和yaml。
我创建了一个yaml,其中类名为KEY,字段名为VALUE
YAML:


# test placeholders

project:
  test:
    service:
      computator:
        # exclude field from beeing randomly valorized
        population:
          exclude:
            InputClass: 'myDate'
            AnotherClass: 'myName'

排除填充属性:

@Data
@Component
@ConfigurationProperties(prefix = "project")
public class ExcludePopulationProperties {

    private Test test;

    @Data
    public static class Test {
        private Service service;
    }

    @Data
    public static class Service {
        private Computator computator;
    }

    @Data
    public static class Computator {
        private Population population;
    }

    @Data
    public static class Population {
        private Map<String, String> exclude;
    }

}

使用JUnit 5进行测试:

@ContextConfiguration(classes = { ExcludePopulationProperties.class })
@ExtendWith(SpringExtension.class)
class YamlTest {

    @Autowired
    private ExcludePopulationProperties excludePopulationProperties;

    @Test
    void testExternalConfiguration() {
        Map<String, String> map = excludePopulationProperties.getTest().getService().getComputator().getPopulation().getExclude();
        assertNotNull(map);
    }

问题是我遇到了一个NullPointerException,因为测试为null

因此,我不确定这里出了什么问题,我希望Map填充正确。
我还试着加上

@TestPropertySource(properties = { "spring.config.location=classpath:application-_test.yaml" })

在Yaml测试中

tez616oj

tez616oj1#

您的ExcludePopulationProperties类不应使用@Component进行注解。相反,您应该在项目中的配置类上使用@EnableConfigurationProperties(ExcludePopulationProperties.class)注解(主应用程序类将正常工作)。
将属性类更改为如下所示(删除@Component):

@Data
@ConfigurationProperties(prefix = "project")
public class ExcludePopulationProperties {
   ...
}

更改应用程序类以启用配置属性:

@SpringBootApplication
@EnableConfigurationProperties(ExcludePopulationProperties.class)
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

YamlTest类如下所示(使用@SpringBootTest):

@SpringBootTest
@ContextConfiguration(classes = { DemoApplication.class })
@TestPropertySource(properties = { "spring.config.location=classpath:application-test.yaml" })
class YamlTest {

    @Autowired
    private ExcludePopulationProperties excludePopulationProperties;

    @Test
    void testExternalConfiguration() {
        Map<String, String> map = excludePopulationProperties.getTest().getService().getComputator().getPopulation().getExclude();
        assertNotNull(map);
        assertEquals(map.get("InputClass"), "myDate");
        assertEquals(map.get("AnotherClass"), "myName");
    }
}
vof42yt1

vof42yt12#

有了这些小的变化,现在我能够测试的属性从YAML文件。
我稍微改进了一下yaml:


# test placeholders

project:
  test:
    service:
      computator:
        # exclude field from beeing randomly valorized
        population:
          exclude:
            InputClass: 
               - 'myDate'
            AnotherClass: 
               - 'myName'

所以现在ExcludePopulationProperties有一个Map〈String,List〉而不是Map〈String,String〉,这样我就可以从同一个类中排除多个字段:

@Data
@Configuration
@ConfigurationProperties(prefix = "project")
@PropertySource(value = "classpath:application-_test.yaml", factory = YamlPropertySourceFactory.class)
public class ExcludePopulationProperties {

    private Test test;

    @Data
    public static class Test {
        private Service service;
    }

    @Data
    public static class Service {
        private Computator computator;
    }

    @Data
    public static class Computator {
        private Population population;
    }

    @Data
    public static class Population {
        private Map<String, List<String>> exclude;
    }

}

YamlPropertySourceFactory是Baeldung在本指南中实现的类:在Sping Boot 中使用YAML文件的@PropertySource

public class YamlPropertySourceFactory implements PropertySourceFactory {

    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
        YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
        factory.setResources(resource.getResource());

        Properties properties = factory.getObject();

        return new PropertiesPropertySource(resource.getResource().getFilename(), properties);
    }

}

测试类别:

@EnableConfigurationProperties
@ContextConfiguration(classes = { ExcludePopulationProperties.class })
@TestPropertySource(properties = { "spring.config.location=classpath:application-_test.yaml" })
@ExtendWith(SpringExtension.class)
class YamlTest {

    @Autowired
    private ExcludePopulationProperties excludePopulationProperties;

    @Test
    void testExternalConfiguration() {
        Map<String, List<String>> map = excludePopulationProperties.getTest().getService().getComputator().getPopulation().getExclude();
        assertNotNull(map);
    }

}

请注意,对于Mockito,您需要同时使用SpringExtension和MockitoExtension:

@EnableConfigurationProperties
@ContextConfiguration(classes = { ExcludePopulationProperties.class })
@Extensions({
        @ExtendWith(SpringExtension.class),
        @ExtendWith(MockitoExtension.class)
})
class YamlTest {

}

更新

我找到了一个更好的解决方案,以避免在所有测试类上都写注解。
添加Jacksonjackson-dataformat-yaml依赖项

<dependency>
  <groupId>com.fasterxml.jackson.dataformat</groupId>
  <artifactId>jackson-dataformat-yaml</artifactId>
  <version>${jackson-dataformat-yaml.version}</version>
</dependency>

配置属性类将为:

@Data
public class ExcludePopulationProperties {

    private Project project;

    @Data
    public static class Project {
        private Test test;
    }

    @Data
    public static class Test {
        private Service service;
    }

    @Data
    public static class Service {
        private Computator computator;
    }

    @Data
    public static class Computator {
        private Population population;
    }

    @Data
    public static class Population {
        private Map<String, List<String>> exclude;
    }

    public static ExcludePopulationProperties build() throws IOException {
        InputStream inputStream = new FileInputStream(new File("./src/test/resources/" + "application-_test.yaml"));
        YAMLMapper mapper = new YAMLMapper();
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        mapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
        return mapper.readValue(inputStream, ExcludePopulationProperties.class);
    }

}

然后,在任何需要的地方,只需调用静态构建方法,测试类将更加简单:

@ExtendWith(SpringExtension.class)
class YamlTest {

    @Test
    void testExternalConfiguration() throws IOException {
        Map<String, List<String>> map = ExcludePopulationProperties.build().getProject().getTest().getService().getComputator().getPopulation().getExclude();
        assertNotNull(map);
    }

}

相关问题