我试图在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。代码已更新
答案 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;
}
}
无法使用
@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);
}