Профиль Spring-boot по умолчанию для интеграционных тестов
Spring-boot использует профили Spring ( http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html), которые позволяют, например, иметь отдельную конфигурацию для разных сред. Одним из способов использования этой функции является настройка тестовой базы данных для использования интеграционными тестами. Интересно, однако, необходимо ли создать свой собственный профиль 'test' и явно активировать этот профиль в каждом тестовом файле? Прямо сейчас я делаю это следующим образом:
- Создайте application-test.properties внутри src / main / resources
- Написать тестовый конфиг там (только имя базы данных на данный момент)
В каждый тестовый файл входят:
@ActiveProfiles("test")
Есть ли более умный / более краткий способ? Например, тестовый профиль по умолчанию?
Изменить 1: Этот вопрос относится к Spring-Boot 1.4.1
14 ответов
Насколько я знаю, нет ничего, что напрямую отвечает на ваш запрос - но я могу предложить предложение, которое могло бы помочь:
Вы можете использовать свою собственную тестовую аннотацию, которая представляет собой метааннотацию, содержащую @SpringBootTest
а также @ActiveProfiles("test")
, Поэтому вам все еще нужен выделенный профиль, но не разбрасывайте определение профиля по всему тесту.
Эта аннотация будет по умолчанию для профиля test
и вы можете переопределить профиль, используя метааннотацию.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@SpringBootTest
@ActiveProfiles
public @interface MyApplicationTest {
@AliasFor(annotation = ActiveProfiles.class, attribute = "profiles") String[] activeProfiles() default {"test"};
}
Другой способ сделать это - определить базовый (абстрактный) тестовый класс, который будут расширены вашими фактическими тестовыми классами:
@RunWith(SpringRunner.class)
@SpringBootTest()
@ActiveProfiles("staging")
public abstract class BaseIntegrationTest {
}
Конкретный тест:
public class SampleSearchServiceTest extends BaseIntegrationTest{
@Inject
private SampleSearchService service;
@Test
public void shouldInjectService(){
assertThat(this.service).isNotNull();
}
}
Это позволяет извлечь больше, чем просто @ActiveProfiles
аннотаций. Можно также представить более специализированные базовые классы для различных видов интеграционных тестов, например, уровень доступа к данным или уровень обслуживания, или для функциональных особенностей (общие @Before
или же @After
методы и т. д.).
Вы можете поместить файл application.properties в папку test/resources. Там вы установили
spring.profiles.active=test
Это своего рода профиль тестирования по умолчанию при выполнении тестов.
Приходите 2021 и Spring Boot 2.4, решение, которое я нашел, - иметь 3 файла свойств.
- - содержит свойства приложения по умолчанию
- - устанавливает профиль в "test" и импортирует свойства из "main"
- - содержит профили для конкретных тестов, которые имеют приоритет над основным
Вот содержание
src/test/resources/application.yml
:
# for testing, set default profile to 'test'
spring.profiles.active: "test"
# and import the 'main' properties
spring.config.import: file:src/main/resources/application.yml
Например, если
src/main/resources/application.yml
имеет содержание
ip-address: "10.7.0.1"
username: admin
и
src/test/resources/application-test.yml
имеет
ip-address: "999.999.999.999"
run-integration-test: true
Затем (при условии, что других профилей нет)...
при запуске тестов,
profiles=test
--
ip-address=999.999.999.999
username=admin
run-integration-test=true
и при обычном запуске приложения
profiles=none
--
ip-address=10.7.0.1
username=admin
run-integration-test <undefined>
Демонстрационный способ сделать это (на самом деле, незначительный твик к первоначальному ответу @Compito):
- Задавать
spring.profiles.active=test
вtest/resources/application-default.properties
, - добавлять
test/resources/application-test.properties
для тестов и переопределить только те свойства, которые вам нужны.
Вы можете поместить свои свойства теста в src/test/resources/config/application.properties
.
Свойства, определенные в этом файле, переопределят те, которые определены в src/main/resources/application.properties
во время тестирования.
Дополнительные сведения о том, почему это работает, см. В документации Spring Boots.
Если вы используете maven, вы можете добавить это в pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<argLine>-Dspring.profiles.active=test</argLine>
</configuration>
</plugin>
...
Затем maven должен запустить ваши интеграционные тесты (*IT.java), используя этот метод, а также IntelliJ начнет с активированным этим профилем - так что вы сможете указать все свойства внутри
application-test.yml
и вам не нужны свойства "-default".
Для активации "тестового" профиля напишите в свой build.gradle:
test.doFirst {
systemProperty 'spring.profiles.active', 'test'
activeProfiles = 'test'
}
В моем случае у меня разные application.properties в зависимости от среды, например:
application.properties (base file)
application-dev.properties
application-qa.properties
application-prod.properties
и application.properties содержит свойство spring.profiles.active для выбора правильного файла.
Для своих интеграционных тестов я создал новый application-test.properties
файл внутри test/resources
и с @TestPropertySource({ "/application-test.properties" })
аннотация это файл, который отвечает за выбор приложения. свойства, которые я хочу, в зависимости от моих потребностей в этих тестах
Еще один программный способ сделать это:
import static org.springframework.core.env.AbstractEnvironment.DEFAULT_PROFILES_PROPERTY_NAME;
@BeforeClass
public static void setupTest() {
System.setProperty(DEFAULT_PROFILES_PROPERTY_NAME, "test");
}
Работает отлично.
Обычно я делал базовый класс для всех интеграционных тестов с общим кодом и аннотациями. Не забудь сделать это
abstract
чтобы не инстатировать. Например:
@SpringBootTest
@Transactional
@AutoConfigureMockMvc
@ActiveProfiles("test")
public abstract class AbstractControllerTest {
@Autowired
protected MockMvc mockMvc;
protected ResultActions perform(MockHttpServletRequestBuilder builder) throws Exception {
return mockMvc.perform(builder);
}
}
// All annotations are inherited
class AccountControllerTest extends AbstractControllerTest {
....
Если вы просто хотите установить / использовать профиль по умолчанию во время сборки через maven, тогда передайте аргумент
-Dspring.profiles.active=test
Как
mvn clean install -Dspring.profiles.active=dev
Лучшее решение, которое я нашел, - это последнее предложение здесь: https://inspeerity.com/blog/setting-default-spring-profile-for-tests-with-override-option/ Автор также очень четко описывает проблему и обсуждает обратная сторона любого другого подхода, о котором я могу думать.
Создать файл
application-default.properties
в ваших тестовых ресурсах, содержащих одну строку:
spring.profiles.active=test
Это использует тот факт, что Spring автоматически включает профиль «по умолчанию», если никакие другие профили не были заданы явно. Теперь ваш
application-test.properties
файл будет использоваться по умолчанию для всех тестов.
Добавлять spring.profiles.active=tests
в вашем файле application.properties вы можете добавить несколько файлов свойств в ваше приложение весенней загрузки, например: application-stage.properties
, application-prod.properties
и т. д. И вы можете указать в своем файле application.properties, а файл для ссылки, добавив spring.profiles.active=stage
или же spring.profiles.active=prod
Вы также можете передать профиль во время запуска приложения весенней загрузки, введя команду:
java -jar
-Dspring.profiles.active=local
build/libs/turtle-rnr-0.0.1-SNAPSHOT.jar
По названию профиля подбирается файл свойств, в приведенном выше случае прохождение профиля local
рассмотреть application-local.properties
файл