Как тестировать классы с @ConfigurationProperties и @Autowired
Я хочу протестировать небольшие части приложения, которые полагаются на свойства, загруженные с помощью @Autowired
и @ConfigurationProperties
. Я ищу решение, загружающее только требуемые свойства, а не всегда все ApplicationContext
.
Вот как сокращенный пример:
@TestPropertySource(locations = "/SettingsTest.properties")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {TestSettings.class, TestConfiguration.class})
public class SettingsTest {
@Autowired
TestConfiguration config;
@Test
public void testConfig(){
Assert.assertEquals("TEST_PROPERTY", config.settings().getProperty());
}
}
Класс конфигурации:
public class TestConfiguration {
@Bean
@ConfigurationProperties(prefix = "test")
public TestSettings settings (){
return new TestSettings();
}
}
Класс настроек:
public class TestSettings {
private String property;
public String getProperty() {
return property;
}
public void setProperty(String property) {
this.property = property;
}
}
Файл свойств в папке ресурсов содержит запись:
test.property=TEST_PROPERTY
В моей текущей конфигурации config не является нулевым, но поля не доступны.
Причина, по которой поля не являются полями, должна быть связана с тем, что я использую не Springboot, а Spring.
Так какой же будет способ Springboot для его запуска?
Редактирование:
Причина, по которой я хочу сделать это: у меня есть анализатор, который анализирует текстовые файлы, используемые регулярные выражения хранятся в файле свойств.
Чтобы проверить это, я хотел бы загрузить только свойства, необходимые для этого синтаксического анализатора, которые находятся в примере над TestSettings.
Читая комментарии, я уже заметил, что это больше не модульные тесты. Однако использование полной конфигурации загрузки Spring для этого небольшого теста кажется мне слишком сложным. Вот почему я спросил, есть ли возможность загружать только один класс со свойствами.
Ответы
Ответ 1
Пара точек:
-
Вам не нужен класс TestConfiguration в основном пакете, потому что все, что он делает, настраивает "TestSettings" bean. Вы можете сделать это просто, аннотируя сам класс TestSettings.
-
Обычно вы загружаете контекст, необходимый для теста, с помощью аннотации @SpringApplicationConfiguration, передавая имя вашего класса Application. Однако вы сказали, что не хотите загружать весь ApplicationContext (хотя это и не понятно почему), поэтому вам нужно создать специальный класс конфигурации для загрузки только для тестов. Ниже я называю это "TestConfigurationNew", чтобы избежать путаницы с классом TestConfiguration, который вы изначально имели.
-
В мире загрузки Spring все свойства обычно хранятся в файле "application.properties"; но их можно хранить в другом месте. Ниже я указал файл "SettingsTest.properties", который вы предложили. Обратите внимание, что вы можете иметь две копии этого файла, одну из которых находится в папке main/resources, а также одну в тестовой/ресурсной папке для тестирования.
Измените код следующим образом:
TestSettings.java(в основном пакете)
@Configuration
@ConfigurationProperties(prefix="test", locations = "classpath:SettingsTest.properties")
public class TestSettings {
private String property;
public String getProperty() {
return property;
}
public void setProperty(String property) {
this.property = property;
}
}
SettingsTest.java(в тестовом пакете)
@TestPropertySource(locations="classpath:SettingsTest.properties")
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = TestConfigurationNew.class)
public class SettingsTest {
@Autowired
TestSettings settings;
@Test
public void testConfig(){
Assert.assertEquals("TEST_PROPERTY", settings.getProperty());
}
}
TestConfigurationNew.java(в тестовом пакете):
@EnableAutoConfiguration
@ComponentScan(basePackages = { "my.package.main" })
@Configuration
public class TestConfigurationNew {
}
Теперь это должно работать так, как вы хотели.
Ответ 2
Вам необходимо аннотировать ваш TestConfiguraion с помощью @EnableConfigurationProperties
следующим образом:
@EnableConfigurationProperties
public class TestConfiguration {
@Bean
@ConfigurationProperties(prefix = "test")
public TestSettings settings (){
return new TestSettings();
}
}
Также вам нужно включить TestConfiguration.class
в @ContextConfiguration
из вас SettingsTest
class:
@TestPropertySource(locations = "/SettingsTest.properties")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfiguration.class)
public class SettingsTest {
...
Ответ 3
вы можете просто добавить @EnableConfigurationProperties в свой @SpringBootTest напрямую.
например:
@ActiveProfiles("test")
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestConfiguration.class)
@EnableConfigurationProperties
...
Ответ 4
Если вы используете Spring Boot, теперь вам нужно только:
@RunWith(SpringRunner.class)
@SpringBootTest
Никаких дополнительных @ContextConfiguration
, никаких дополнительных классов только для тестов на EnableAutoConfiguration
и EnableConfigurationProperties
. Вам не нужно указывать класс конфигурации для загрузки, все они будут загружены.
Но, убедитесь, что записи свойств, которые вы хотите прочитать в main/resources/application.yml
, также присутствуют в test/resources/application.yml
. Повторение неизбежно.
Другой способ:
- Определите класс конфигурации только для тестов вместе с
MyApplicationTest.java
на том же уровне. Этот класс может быть пустым.
Как:
@EnableAutoConfiguration
@EnableConfigurationProperties(value = {
ConnectionPoolConfig.class
})
public class MyApplicationTestConfiguration {
}
- И, в классе, чтобы загрузить конфигурацию автоматической проводки.
Как:
@RunWith(SpringRunner.class)
//@SpringBootTest // the first, easy way
@ContextConfiguration(classes = MyApplicationTestConfiguration.class,
initializers = ConfigFileApplicationContextInitializer.class)
public class ConnectionPoolConfigTest {
@Autowired
private ConnectionPoolConfig config;
По сути, вы:
- используйте определенную конфигурацию для
@EnableConfigurationProperties
и @EnableAutoConfiguration
, перечисляя все файлы @ConfigurationProperties
, которые вы хотите загрузить
- в тестовом классе вы загружаете этот файл конфигурации тестов с классом инициализатора, определенным Spring для загрузки файла
application.yml
.
И поместите значения для загрузки в test/resources/application.yml
. Повторение неизбежно. Если вам нужно загрузить другой файл, используйте @TestProperties()
с указанием местоположения. Примечание: @TestProperties
поддерживает только файлы .properties
.
Оба способа работают для значений загрузки класса конфигурации
- либо из
application.yml
/application.properties
- или из другого файла свойств, указанного в
PropertySource
, например @PropertySource(value = "classpath:threadpool.properties")
Важно
Последние заметки из Spring doc, согласно здесь
Некоторые люди используют Project Lombok для автоматического добавления методов получения и установки. Убедитесь, что Lombok не генерирует какой-либо конкретный конструктор для такого типа, так как он автоматически используется контейнером для создания экземпляра объекта.
Наконец, рассматриваются только стандартные свойства Java Bean, и привязка к статическим свойствам не поддерживается.
Это означает, что если у вас есть [email protected]
без @NoArgsConstructor
или @AllArgsConstructor
, внедрение свойств не произойдет, потому что он видит только невидимый конструктор, созданный @Builder
. Так что не забудьте использовать ни один, или все эти аннотации!