112

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

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

如果我用注释配置应用程序上下文,我看不到在 spring 上下文初始化之前我可以做某事的钩子。

4

9 回答 9

143

您可以在静态初始化程序中初始化 System 属性:

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

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

}

静态初始化代码将在 spring 应用程序上下文初始化之前执行。

于 2012-08-27T14:48:17.100 回答
103

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

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

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

于 2016-03-03T04:45:23.107 回答
17

还可以使用测试 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
{
...
}

如果应该为所有单元测试设置某个系统属性,则可以避免代码重复。

于 2016-12-23T17:21:31.140 回答
15

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

环境变量.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"));
   }
 }
于 2019-04-09T22:18:11.387 回答
7

如果你希望你的变量对所有测试都有效,你可以application.properties在你的测试资源目录中有一个文件(默认情况下:)src/test/resources,它看起来像这样:

MYPROPERTY=foo

然后它将被加载和使用,除非您有定义 via@TestPropertySource或类似的方法 - 加载属性的确切顺序可以在 Spring 文档第24 章中找到。外部化配置

于 2018-03-02T10:59:57.590 回答
3

您可以将系统属性设置为 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 部分下选择您的测试类。

3)执行以下操作:

在此处输入图像描述

于 2018-09-03T09:57:34.243 回答
3

对于单元测试,当我执行“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>
于 2019-04-26T23:31:19.220 回答
2

对于springboot,我认为这是最简单的方法,@SpringBootTest可以使用java中的注释:

@SpringBootTest(
    properties = { "spring.application.name=example", "ENV_VARIABLE=secret" }
)
public class ApplicationTest {

    // Write your tests here

}

或者在 kotlin 中你可以这样做:

@SpringBootTest(
    properties = ["spring.application.name=example", "ENV_VARIABLE=secret"]
)
internal class ApplicationKTest {

    // Write your tests here

}

就是这样,您的测试应该使用您在注释中定义的属性覆盖属性。假设您application.yml看起来像这样:

spring:
  application:
    name: "app"

db:
  username: "user"
  password: ${ENV_VARIABLE:default}

然后在测试期间它将是:

  • spring 属性spring.application.name将返回值"example"
  • 环境变量ENV_VARIABLE将返回"secret",因此如果您db.password在代码中使用该值,它将返回"secret"
于 2021-09-16T16:10:19.223 回答
1

如果您有很多测试类(启动 tomcat/server 的 IT 测试),并且测试失败,您需要使用 System.setProperty("ccm.configs.dir", configPath); 设置系统属性;由于您需要确保在 spring 开始之前设置它,因此您需要将它放在类中的静态上下文中。并确保任何可能依赖它的测试都获得此设置的系统属性,请在您的测试文件夹中定义一个简单的配置类来设置该变量。PS在我的情况下,所需的环境变量是“ccm.configs.dir”这是我在测试文件夹中添加的内容,

@Configuration
public class ConfigLoader {
  static {
    
    System.setProperty("ccm.configs.dir", "path/to/the/resource");
  }

}

我所有的集成测试类都能够在它们运行时获得已经设置的变量。

于 2021-11-19T23:05:12.840 回答