如何在春季测试中设置环境变量或系统属性?


93

我想编写一些测试来检查已部署WAR的XML Spring配置。不幸的是,某些bean需要设置一些环境变量或系统属性。通过@ContextConfiguration使用便捷的测试样式时,如何在初始化Spring bean之前设置环境变量?

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

如果我使用注释配置应用程序上下文,那么在初始化spring上下文之前,我看不到可以执行某些操作的钩子。

Answers:


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-

谢谢你 静态的东西不起作用,但是@BeforeClass的一个小方法起作用了!
Midhun Agnihotram

如果更改Log4j2配置文件属性,则该机制不起作用。似乎在该静态代码段之前反正正在加载Spring(并因此错误地记录了日志)。
lucasvc

86

从Spring 4.1开始,正确的方法是使用@TestPropertySource批注。

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

请参阅Spring文档Javadocs中的@TestPropertySource 。


2
该注释还支持属性文件路径。
MigDus

2
我可以在测试期间使用@TestPropertySource(properties={"spring.cloud.config.label=feature/branch"})
Marcello de Sales

4
好的答案,但是遗憾的是,对于Spring 4.2.9,该属性始终为空。仅静态块有效...对于应用程序属性有效,但对于系统属性无效。
格雷戈尔'18

首先,我看到并尝试了静态版本(该版本有效),但是此Annotation更加清晰,而且更可取(对我而言,它也像一种魅力一样工作)。
BAERUS

3
这提供了Environment与“环境变量”不同的属性。
OrangeDog

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引导2.X和JUnit 5.x的(用完美的作品@SpringBootTest或任何的测试切片注释)
维姆Deblauwe

10

目前,这里所有的答案都只讨论系统属性,这些属性与设置较复杂的环境变量(尤其是环境变量)不同。用于测试。值得庆幸的是,下面的类可以用于此,并且类文档中有很好的示例

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规则是第三方库的一部分,使用hacky反射更改JVM内存中环境的缓存值,甚至不使用实际的环境变量。因此,我不想使用它或建议任何人使用它。
克里斯蒂安

4

如果您希望变量对所有测试均有效,则可以application.properties在测试资源目录中拥有一个文件(默认为:),该文件src/test/resources如下所示:

MYPROPERTY=foo

除非您通过@TestPropertySource或类似方法进行定义,否则将加载并使用它-加载属性的确切顺序可以在Spring文档第24章“ 外部化配置”中找到


2

您可以将系统属性设置为VM参数。

如果您的项目是Maven项目,则可以在运行测试类时执行以下命令:

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

测试类别:

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

如果要在Eclipse中运行单个测试类或方法,则:

1)转到运行->运行配置

2)在左侧的Junit部分下,选择您的Test类。

3)执行以下操作:

在此处输入图片说明


2

对于单元测试,当我执行“ mvn clean install”时,尚未实例化System变量,因为没有服务器在运行该应用程序。因此,为了设置系统属性,我需要在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>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.