Перейдіть за замовчуванням налаштування Spring-Boot application.properties в Junit Test


198

У мене є програма Spring-Boot, де властивості за замовчуванням встановлюються у application.propertiesфайлі classpath (src / main / ресурси / application.properties).

Я хотів би замінити деякі параметри за замовчуванням у своєму тесті JUnit із властивостями, задекларованими у test.propertiesфайлі (src / test / ресурси / test.properties)

У мене зазвичай є спеціальний клас Config для моїх тестів Junit, наприклад

package foo.bar.test;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import(CoreConfig.class)
@EnableAutoConfiguration
public class TestConfig {

}

Я спершу подумав, що використання @PropertySource("classpath:test.properties")класу TestConfig зробить трюк, але ці властивості не замінять налаштування application.properties (див. Довідковий документ Spring-Boot Doc - 23. Externalized Configuration ).

Потім я спробував використовувати, -Dspring.config.location=classpath:test.propertiesколи викликав тест. Це було успішно - але я не хочу встановлювати це властивість системи для кожного виконання тесту. Таким чином я вклав це в код

@Configuration
@Import(CoreConfig.class)
@EnableAutoConfiguration
public class TestConfig {

  static {
    System.setProperty("spring.config.location", "classpath:test.properties");
  }

}

що, на жаль, знову не було успішним.

Має бути просте рішення про те, як замінити application.propertiesналаштування в тестах JUnit, на test.propertiesщо я, мабуть, не звернув уваги.


Якщо вам потрібно налаштувати лише декілька властивостей, ви можете використовувати нову анотацію @DynamicPropertySource. stackoverflow.com/a/60941845/8650621
Феліпе Десідерати

Відповіді:


293

Ви можете використовувати @TestPropertySourceдля перевизначення значень у application.properties. З його javadoc:

Джерела властивостей тесту можуть використовуватися для вибіркового перебору властивостей, визначених у джерелах властивостей системи та додатків

Наприклад:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = ExampleApplication.class)
@TestPropertySource(locations="classpath:test.properties")
public class ExampleApplicationTests {

}

2
Це воно. Дякую. На жаль, він не працює при використанні на ExampleApplication.class, тому я повинен встановити його на кожному тестовому класі. Це так?
FrVaBe

1
Він повинен пройти десь в ієрархії тестового класу, тобто ви можете використовувати загальний надклас для налаштування його на декілька різних тестових класів.
Енді Вілкінсон

64
Також зауважте, що ви @TestPropertySourceможете прийняти propertiesаргумент, щоб перезаписати якусь властивість у рядок, наприклад @TestPropertySource(properties = "myConf.myProp=valueInTest"), це корисно у випадку, якщо вам не потрібен абсолютно новий файл властивості.
день

2
Ви можете вказати декілька файлів у масиві, а також файли у файловій системі (але пам’ятайте, що вони можуть не працювати на сервері CI):@TestPropertySource(locations={"file:C:/dev/...","classpath:test.properties"})
Adam

8
Зауважте, що @SpringApplicationConfigurationце вже застаріло, і вам слід скористатися@SpringBootTest
mrkernelpanic

74

Весна завантаження автоматично завантажується src/test/resources/application.properties , якщо використовуються наступні примітки

@RunWith(SpringRunner.class)
@SpringBootTest

Отже, перейменуйте test.properties до application.propertiesвикористовувати автоматичну конфігурацію.

Якщо вам потрібно * лише * завантажити файл властивостей (у навколишнє середовище), ви також можете скористатися наступним, як пояснено тут

@RunWith(SpringRunner.class)
@ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class) 

[ Оновлення: Переосмислення певних властивостей для тестування ]

  1. Додайте src/main/resources/application-test.properties .
  2. Анотувати тестовий клас с @ActiveProfiles("test") .

Це завантажує, application.propertiesа потім application-test.properties властивості в контекст програми для тестового випадку, як визначено правилами тут .

Демо - https://github.com/mohnish82/so-spring-boot-testprops


1
Не впевнений, чи є гарною ідеєю мати два application.propertiesфайли на classpath (один в src/main/resourcesі один в src/test/resources). Хто гарантує, що обидва будуть взяті, а хто - перший?
FrVaBe

3
@FrVaBe Весна збирається гарантувати це! Основні властивості профілю завжди завантажуються. Потім під час фази випробування завантажуються властивості тестування, додаючи / переосмислюючи нові / існуючі властивості. Якщо вам не подобається тримати два файли з однаковими іменами, то ви можете додати application-test.propertiesв src/main/resourcesі вказати в testякості активного профілю в тесті.
Моніш

7
Весна не дає гарантії. Інструмент збирання використовуватиме тестові ресурси на користь основних ресурсів під час тестів. Але у випадку тестової програми.властивості, головне application.properties буде проігноровано. Це не те, що я хочу, тому що основне містить декілька корисних значень за замовчуванням, і мені потрібно лише замінити деякі з них під час тесту (і я не хочу дублювати весь файл у розділі тесту). Дивіться тут .
FrVaBe

6
Ви правильні, src/test/resources/application.propertiesпід час тестового завантаження завантажуються лише властивості, визначені в , src/main/resources/application.propertiesігнорується.
Моніш

11
Якщо ви поки не використовуєте профілі, вам не потрібен спеціальний "тестовий" профіль. Просто назвіть свої тестові властивості, application-default.propertiesі вони будуть враховані, оскільки ви автоматично запускаєте профіль "за замовчуванням" (якщо не оголошено жодного іншого).
FrVaBe

65

Ви також можете використовувати мета-примітки для зовнішньої настройки конфігурації. Наприклад:

@RunWith(SpringJUnit4ClassRunner.class)
@DefaultTestAnnotations
public class ExampleApplicationTests { 
   ...
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@SpringApplicationConfiguration(classes = ExampleApplication.class)
@TestPropertySource(locations="classpath:test.properties")
public @interface DefaultTestAnnotations { }

21

Інший підхід, який підходить для переосмислення кількох властивостей у вашому тесті, якщо ви використовуєте @SpringBootTestпримітку:

@SpringBootTest(properties = {"propA=valueA", "propB=valueB"})

1
це SpringBootTestзавантажити файл application.properties?
TuGordoBello

8

TLDR:

Тож, що я зробив, це мати стандарт, src/main/resources/application.propertiesа також src/test/resources/application-default.propertiesде я перекриваю деякі настройки для ВСІХ тестів.

Ціла історія

Я зіткнувся з тією ж проблемою і поки що не використовував профілі. Здавалося, нудно робити це зараз і пам’ятати про декларування профілю - який можна легко забути.

Трюк полягає в тому, щоб використовувати загальний профіль, який визначає особливості application-<profile>.propertiesпрофілю. Див. Https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-profile-specific-properties .


3

Просте пояснення:

Якщо ви схожі на мене , і у вас є те ж саме application.propertiesв src/main/resourcesі src/test/resources, і ви цікаво , чому application.propertiesу вашій папці тестів не перекриваючиapplication.properties в основних ресурсах, читайте далі ...

Якщо у вас є application.propertiesпід src/main/resourcesі той же application.propertiesпід src/test/resources, який application.propertiesотримує взяв, залежить від того, як ви працюєте тести . Папка структура src/main/resources і src/test/resourcesє Maven архітектурного угодою, так що якщо ви запускаєте тест , як mvnw testабо навіть gradlew test, то application.propertiesв src/test/resourcesбуде отримати взяли, так як тест шлях до класів будуть передувати основний шлях до класів. Але, якщо ви запускаєте тест , як Run as JUnit Testв ELIPSE / STS, то application.propertiesв src/main/resourcesбуде отримати взяв, як і основні шляхи до класам передують тест класи.

Ви можете перевірити це, відкривши Run > Run Configurations > JUnit > *your_run_configuration* > Click on "Show Command Line".

Ви побачите щось на кшталт:

XXXbin \ javaw.exe -ea -Dfile.encoding = UTF-8 -classpath XXX \ workpace-spring-tool-suite-4-4.5.1.RELEASE \ project_name \ bin \ main; XXX \ workpace-spring-tool-suite-4-4.5.1.RELEASE \ project_name \ bin \ test;

Ви бачите, що спочатку надходить \ main , а потім \ test ? Правильно, це все про класний шлях :-)

Ура


1
I just configured min as the following :

spring.h2.console.enabled=true
spring.h2.console.path=/h2-console


# changing the name of my data base for testing
spring.datasource.url= jdbc:h2:mem:mockedDB
spring.datasource.username=sa
spring.datasource.password=sa



# in testing i don`t need to know the port

#Feature that determines what happens when no accessors are found for a type
#(and there are no annotations to indicate it is meant to be serialized).
spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false`enter code here`

1

Якщо ви використовуєте Spring 5.2.5 та Spring Boot 2.2.6 і хочете замінити лише декілька властивостей замість усього файлу. Ви можете використовувати нову примітку: @DynamicPropertySource

@SpringBootTest
@Testcontainers
class ExampleIntegrationTests {

    @Container
    static Neo4jContainer<?> neo4j = new Neo4jContainer<>();

    @DynamicPropertySource
    static void neo4jProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.data.neo4j.uri", neo4j::getBoltUrl);
    }
}

0

В іншому випадку ми можемо змінити ім'я конфігуратора властивостей за замовчуванням, встановивши властивість, spring.config.name=testа потім мати ресурс class-path, src/test/test.propertiesнашим рідним екземпляромorg.springframework.boot.SpringApplication буде автоматично налаштований з цього розділеного тесту.

Перевага: автоматична конфігурація тестів;

Недолік: викриття властивості "spring.config.name" на рівні CI

посилання: http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html

spring.config.name = application # Налаштування імені файлу


5
Ігнорування application.propertiesдля мене не є варіантом, оскільки я хочу лише замінити деякі початкові значення конфігурації в тесті.
FrVaBe

Я шукав спосіб провести єдиний тест, який не завантажує src / main / ресурси / application.properties, і це все. Створіть файл: src / test / resources / empty.properties та додайте примітку до тесту (ив), який повинен ігнорувати основні властивості. @TestPropertySource (properties = "spring.config.name = порожній")
rvertigo

Як встановити конкретне значення властивості для кожного методу тестування на юніт?
Ніколя

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.