#java #spring #spring-boot #configuration #nullpointerexception
#java #spring #spring-boot #конфигурация #исключение nullpointerexception
Вопрос:
Я пытаюсь использовать аннотацию значения в Spring для чтения из локального приложения.файл 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;
}
}
И у меня есть класс поставщика конфигурации, который устанавливает средство чтения конфигурации, чтобы мой класс выше мог использовать его для чтения приложения.файл 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 (я предполагаю, что это потому, что configurationReader, который я передаю в качестве параметра методу getConfigValue, равен null):
@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);
}
Я не уверен, действительно ли мой класс считывает значение конфигурации из файла конфигурации на данный момент. Любая помощь будет принята с благодарностью!
PS Код обновлен
Ответ №1:
@Значение
Аннотация Spring @Value предоставляет удобный способ ввода значений свойств в компоненты, а не для указания пути к файлу свойств
@PropertySource Используйте @PropertySource для этого документа
Аннотация, предоставляющая удобный и декларативный механизм для добавления PropertySource в среду Spring. Для использования в сочетании с
@Configuration
классамиУчитывая файл app.properties, содержащий пару ключ / значение
testbean.name=myTestBean
, следующий@Configuration
класс использует@PropertySourc
e для внесения вкладаapp.properties
в набор PropertySources среды.
Пример
@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;
}
}
Файлы YAML не могут быть загружены с помощью
@PropertySource
аннотации. Итак, в случае, если вам нужно загружать значения таким образом, вам необходимо использовать файл свойств.
Переходя к тестовому варианту, вы не должны создавать новый экземпляр DefaultEmailValidator
, который вам нужно использовать @SpringBootTest
@SpringBootTest
Аннотацию можно использовать, когда нам нужно загрузить весь контейнер. Аннотация работает путем создания ApplicationContext, который будет использоваться в наших тестах.
RunWith(SpringRunner.class )
@RunWith (SpringRunner.class ) используется для обеспечения моста между функциями тестирования Spring Boot и JUnit. Всякий раз, когда мы используем какие-либо функции тестирования загрузки Spring в тестах JUnit, эта аннотация будет необходима.
@MockBean
Еще одна интересная вещь здесь — использование @MockBean . Это создает макет
EmailValidatorТест
@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);
}
Комментарии:
1. извините за поздний ответ 🙂 Я попробовал выше и все еще получаю NPE для строки
String a = validator.getConfigValue(configurationReader,"mail.subject.max.length");
. И я создалapplication.properties
файл и поместил его вdomain
папку, а также поставил@Value("${configFilesPath:./domain/application.properties}")
выше @Getter для пути к файлу. Я делаю что-то не так?2. дайте мне знать, если вы хотите, чтобы я открыл еще один билет для NPE 🙂