【问题标题】:How to Set Environment Varibles for Junit Tests with Spring Framework如何使用 Spring Framework 为 Junit 测试设置环境变量
【发布时间】:2019-03-11 17:27:43
【问题描述】:

我有一个简单地返回带有System.getEnv 的环境变量的类,我正在尝试为它编写一个JUnit 测试,但我总是得到空值。 我正在尝试使用设置了所有变量的application-test.yml,并尝试了许多注释,例如

@RunWith(SpringJUnit4ClassRunner.class)
@TestPropertySource(locations="classpath:/application-test.yml")

还有很多其他的,但仍然没有成功。有谁知道如何简单地做到这一点?

【问题讨论】:

  • 为什么不使用 PowerMock 模拟 System 类?或者你可以试试here
  • 我不认为 PowerMock 是 Spring Framework 的一部分,对吧?不幸的是,对于政策,我只能使用官方的春季课程。我在链接的线程中尝试了解决方案,但仍然为空。
  • 你在做什么类型的测试?是单元还是集成?

标签: spring-boot junit4


【解决方案1】:

Spring 与环境变量无关。与系统属性不同,它可以读取它们,但据我所知没有说任何内容。

环境变量应该存在于环境中。

所以你有以下选择:

选项 1

使用允许模拟静态方法调用的 Power Mock。这个库不是 spring 的一部分,所以你可以在测试范围内使用它,这样它就不会影响生产(powermock jar 不会在生产依赖项列表中)

选项 2

使用一些外部类包装静态调用,然后使用常规模拟框架对其进行模拟/或加载同一接口的不同 bean,因为无论如何您都在使用 Spring Test。代码将如下所示:

  interface EnvAccessor {
       String getValue(String envVarName);
  }

  public class MyEnvAccessor {
       String getValue(String envVarName) {
          return System.getenv(envVarName);
       }
  }

选项 3

在生产代码中什么都不做,而是在 JUnit 测试开始之前以编程方式设置 env 变量:

public class SampleTest {

    @BeforeClass
    public static void setupEnvironment() {
       // set the environment here
    }
}

现在,特别是从测试和一般的 java 代码设置环境非常棘手,因为不应以编程方式更改环境变量。

您可以阅读Here 了解可能的解决方法并在您的程序中对其进行评估。

【讨论】:

    【解决方案2】:

    有多种方法。

    选项 1

    如果您在 IDE(eclipse 或 IntelliJ IDEA)中运行测试,您可以在 IDE 中为测试设置变量。如果您使用的是 maven,您可以通过 Surefire 插件设置系统属性 - https://maven.apache.org/surefire/maven-surefire-plugin/examples/system-properties.html

    <project>
    [...]
    <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.22.0</version>
        <configuration>
          <systemProperties>
            <property>
              <name>buildDir</name>
              <value>${project.build.outputDirectory}</value>
            </property>
          </systemProperties>
        </configuration>
      </plugin>
    </plugins>
    </build>
    [...]
    </project>
    

    选项 2

    使用 Spring EL

    "classpath:config_#{systemProperties['env']}/db.properties" 
    

    更多细节可以在这里找到 - how to read System environment variable in Spring applicationContext

    【讨论】:

      【解决方案3】:

      您遇到的问题是SpringJUnitRunner 在测试类中的任何方法之前在类级别运行。一种解决方案是将 spring 测试包装在父类中,并在该类中设置环境变量。

      这在带有系统存根的 JUnit 5 中更容易实现 - https://github.com/webcompere/system-stubs

      这是一个来自那里的 spring 示例 (https://github.com/webcompere/system-stubs/blob/master/system-stubs-jupiter/src/test/java/uk/org/webcompere/systemstubs/jupiter/examples/SpringAppWithDynamicPropertiesTest.java):

      @ExtendWith(SystemStubsExtension.class)
      public class SpringAppWithDynamicPropertiesTest {
          private static WireMockServer wireMock = new WireMockServer(Options.DYNAMIC_PORT);
      
          // sets the environment before Spring even starts
          @SystemStub
          private static EnvironmentVariables environmentVariables;
      
      
          @BeforeAll
          static void beforeAll() {
              // we can manipulate the env vars here
              environmentVariables.set("SERVER_URL", "something");
          }
      
      
          @Nested
          @SpringBootTest(classes = {RestApi.class, App.class},
              webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
          class InnerSpringTest {
              @LocalServerPort
              private int serverPort;
      
              @Test
              void someTest() {
                  // the spring app is testable with the given env
      
              }
          }
      }
      

      我认为同样可以在 JUnit 4 中实现,外部类使用 Enclosed 运行器,并使用 EnvironmentVariablesRule 作为静态成员,并在外部类的 @BeforeClass 方法中设置环境变量。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-11
        • 1970-01-01
        • 2014-07-02
        • 1970-01-01
        相关资源
        最近更新 更多