Как установить переменную среды или системное свойство в весенних тестах?

95

Я хотел бы написать несколько тестов, которые проверяют конфигурацию XML Spring развернутой WAR. К сожалению, некоторые bean-компоненты требуют, чтобы были установлены некоторые переменные среды или системные свойства. Как я могу установить переменную среды до инициализации Spring beans при использовании удобного стиля тестирования с @ContextConfiguration?

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:whereever/context.xml")
public class TestWarSpringContext { ... }

Если я настраиваю контекст приложения с помощью аннотаций, я не вижу ловушки, где я могу что-то сделать до инициализации контекста Spring.

Ханс-Петер Штёрр
источник

Ответы:

127

Вы можете инициализировать свойство System в статическом инициализаторе:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:whereever/context.xml")
public class TestWarSpringContext {

    static {
        System.setProperty("myproperty", "foo");
    }

}

Код статического инициализатора будет выполнен до инициализации контекста приложения Spring.

Джимми Прет
источник
14
Глупый я - хорошо, это сработает. Даже лучше: вероятно, @BeforeClassспособ установки системного свойства и @AfterClassметод его удаления также будут работать, и после этого будет хорошо очищаться. (Хотя не пробовал.)
Ханс-Петер Штёрр,
1
Пробовал @BeforeClass - и он отлично работал для настройки свойств системы до того, как другие свойства были установлены в тестовом экземпляре
wbdarby
Спасибо за это. Статическая вещь не работала, но небольшой метод с @BeforeClass работал!
Midhun Agnihotram
Этот механизм не работает при изменении свойства файла конфигурации Log4j2. Кажется, что Spring в любом случае загружается (и, следовательно, неправильно регистрирует) перед этим статическим фрагментом кода.
lucasvc
87

Правильный способ сделать это, начиная с Spring 4.1, - использовать @TestPropertySourceаннотацию.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:whereever/context.xml")
@TestPropertySource(properties = {"myproperty = foo"})
public class TestWarSpringContext {
    ...    
}

См. @TestPropertySource в документации Spring и Javadocs .

Раман
источник
2
Эта аннотация также поддерживает путь к файлу свойств.
MigDus
2
Я мог переключить ярлык клиента Spring Cloud Config во время тестов с помощью@TestPropertySource(properties={"spring.cloud.config.label=feature/branch"})
Марчелло де Сэйлс,
5
Хороший ответ, но, к сожалению, у меня не получилось, используя Spring 4.2.9 свойство всегда было пустым. Работал только статический блок ... Работал для свойств приложения, а не для свойств системы.
Грегор
Сначала я увидел и попробовал статическую версию (которая работала), но эта аннотация еще чище и предпочтительнее (для меня, поскольку она также работает как шарм).
BAERUS
4
Это обеспечивает Environmentсвойство, которое отличается от «переменной среды».
OrangeDog 02
11

Также можно использовать тестовый ApplicationContextInitializer для инициализации системного свойства:

public class TestApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>
{
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext)
    {
        System.setProperty("myproperty", "value");
    }
}

а затем настройте его в тестовом классе в дополнение к расположению файла конфигурации контекста Spring:

@ContextConfiguration(initializers = TestApplicationContextInitializer.class, locations = "classpath:whereever/context.xml", ...)
@RunWith(SpringJUnit4ClassRunner.class)
public class SomeTest
{
...
}

Таким образом можно избежать дублирования кода, если для всех модульных тестов необходимо установить определенное системное свойство.

анре
источник
Это также отлично работает с Spring Boot 2.x и Junit 5.x (с использованием @SpringBootTestили любой из аннотаций тестовых срезов )
Вим Деблаув,
11

Все ответы здесь в настоящее время говорят только о системных свойствах, которые отличаются от переменных среды, которые сложнее установить, особенно. для тестов. К счастью, для этого можно использовать класс ниже, и в документации класса есть хорошие примеры

EnvironmentVariables.html

Быстрый пример из документации, измененный для работы с @SpringBootTest

@SpringBootTest
public class EnvironmentVariablesTest {
   @ClassRule
   public final EnvironmentVariables environmentVariables = new EnvironmentVariables().set("name", "value");

   @Test
   public void test() {
     assertEquals("value", System.getenv("name"));
   }
 }
Хариш Гокаварапу
источник
Правила EnvironmentVariables являются частью сторонней библиотеки, используют хакерское отражение для изменения кэшированных значений среды в памяти JVM и даже не используют фактические переменные среды. Поэтому я не хотел бы использовать его и никому рекомендовать это делать.
Кристиан,
4

Если вы хотите, чтобы ваши переменные были действительными для всех тестов, вы можете иметь application.properties файл в каталоге тестовых ресурсов (по умолчанию :), src/test/resourcesкоторый будет выглядеть примерно так:

MYPROPERTY=foo

Затем он будет загружен и использован, если у вас нет определений через @TestPropertySourceили аналогичный метод - точный порядок, в котором загружаются свойства, можно найти в главе 24. Внешняя конфигурация документации Spring .

Blalasaadri
источник
2

Вы можете установить свойства системы как аргументы виртуальной машины.

Если ваш проект является проектом maven, вы можете выполнить следующую команду при запуске тестового класса:

mvn test -Dapp.url="https://stackoverflow.com"

Тестовый класс:

public class AppTest  {
@Test
public void testUrl() {
    System.out.println(System.getProperty("app.url"));
    }
}

Если вы хотите запустить отдельный тестовый класс или метод в eclipse, тогда:

1) Перейдите в Run -> Run Configuration

2) С левой стороны выберите свой тестовый класс в разделе Junit.

3) сделать следующее:

введите описание изображения здесь

Джоби Уилсон Мэтьюз
источник
2

Для модульных тестов системная переменная еще не создается, когда я выполняю «mvn clean install», потому что нет сервера, на котором запущено приложение. Итак, чтобы установить свойства системы, мне нужно сделать это в pom.xml. Вот так:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.21.0</version>
    <configuration>
        <systemPropertyVariables>
            <propertyName>propertyValue</propertyName>
            <MY_ENV_VAR>newValue</MY_ENV_VAR>
            <ENV_TARGET>olqa</ENV_TARGET>
            <buildDirectory>${project.build.directory}</buildDirectory>
        </systemPropertyVariables>
    </configuration>
</plugin>
Ген
источник