Spring-使用值批注从本地配置文件读取

时间:2019-04-21 22:25:44

标签: java spring spring-boot configuration nullpointerexception

我试图在Spring中使用Value批注从与主测试和单元测试类放在同一包中的本地application.yaml文件读取。我有一个简单的类,带有获取配置值的方法:

public class EmailValidator {

    String getConfigValue(configurationProvider1 configurationReader, String configName) {
        String value = null;
        ConfigurationProvider reader;
        try {
            reader = configurationReader.configurationProvider();
            value = reader.getProperty(configName, String.class);
            //the `reader` above is null when I run the test, so I get Null Pointer Exception on this line
            if (value == null) {
                LOGGER.warn("The configuration for " + configName + " cannot be found.");
            }
        } catch (Exception e){
            e.printStackTrace();
        }

        return value;
    }
} 

我有一个配置提供程序类,用于设置配置读取器,以便我上面的类可以利用它来读取application.yaml文件:

@Configuration
@AllArgsConstructor(access = AccessLevel.PACKAGE)
@NoArgsConstructor
@ComponentScan
public class configurationProvider1 {

        @Value("${configFilesPath:./domain/application.properties}")//Not really sure if this is the right way of locating my configuration file
        @Getter
        private String filePath;

        @Bean
        public ConfigurationProvider configurationProvider() throws FileNotFoundException {
            if (!Paths.get(this.filePath).toFile().exists()) {
                throw new FileNotFoundException("Configuration file doesn't exist: " + this.filePath);
            }

            ConfigFilesProvider configFilesProvider =
                    () -> Collections.singletonList(Paths.get(filePath).toAbsolutePath());
            ConfigurationSource source = new FilesConfigurationSource(configFilesProvider);
            Environment environment = new ImmutableEnvironment(this.filePath);

            return new ConfigurationProviderBuilder()
                    .withConfigurationSource(source)
                    .withEnvironment(environment)
                    .build();
        }
    } 

如上所述,我不确定@Value("${configFilesPath:./domain/application.properties}")是否是查找本地application.properties文件的正确方法(这些类位于名为domain的同一程序包中,但配置文件不是在资源文件夹中,因为这是服务层。因此它就位于domain包下)。

当我尝试在我的第一堂课中测试我的getConfigValue方法时,我得到了NPE(我认为是因为我作为参数传递给getConfigValue方法的configurationReader为空):

@RunWith(SpringRunner.class)
@SpringBootTest
public class EmailValidatorTest {

    @MockBean
    private configurationProvider1 configurationReader = mock(configurationProvider1.class);

    @Autowired
    private DefaultEmailValidator validator;//maybe I should inject the dependency somewhere?

    @Test
    public void simple(){
        String a = validator.getConfigValue(configurationReader,"mail.subject.max.length");
        System.out.println(a);
    } 

我不确定目前我的班级是否真的从配置文件中读取配置值。任何帮助将不胜感激!

P.S。代码已更新

1 个答案:

答案 0 :(得分:2)

@Value

  

Spring的@Value注释提供了一种方便的方法来将属性值注入到组件中,而不是提供属性文件路径

@PropertySource 用于该Doc

@PropertySource
  

注释为将PropertySource添加到Spring的环境提供了一种方便的声明性机制。与@Configuration类一起使用

     

给定包含键/值对testbean.name=myTestBean的文件app.properties,以下@Configuration类使用@PropertySourc e向环境的PropertySource集贡献app.properties

示例

 @Configuration
 @PropertySource("classpath:/com/myco/app.properties")
 public class AppConfig {

 @Autowired
 Environment env;

 @Bean
 public TestBean testBean() {
     TestBean testBean = new TestBean();
     testBean.setName(env.getProperty("testbean.name"));
     return testBean;
   }
 }

24.7.4 YAML Shortcomings

  

无法使用@PropertySource注释加载YAML文件。因此,在需要以这种方式加载值的情况下,您需要使用属性文件。

进入测试用例,您不应创建需要使用DefaultEmailValidator

@SpringBootTest的新实例

@SpringBootTest Example

  

当我们需要引导整个容器时,可以使用@SpringBootTest注释。注释通过创建将在我们的测试中使用的ApplicationContext起作用。

RunWith(SpringRunner.class)

  

@RunWith(SpringRunner.class)用于在Spring Boot测试功能和JUnit之间建立桥梁。每当我们在JUnit测试中使用任何Spring Boot测试功能时,都将需要此批注。

@MockBean

  

这里另一个有趣的事情是@MockBean的使用。它会创建一个模拟

EmailValidatorTest

 @RunWith(SpringRunner.class)
 @SpringBootTest
 public class EmailValidatorTest {

@MockBean
private configurationProvider1 configurationReader;

@Autowire
private DefaultEmailValidator validator

@Test
public void testGetConfigValue(){
    String a = validator.getConfigValue(configurationReader,"mail.subject.max.length");
    System.out.println(a);
}