[英]How to unset environment variable before testing in maven
我有一些依賴於環境變量的單元測試。
在使用 maven 進行測試之前,我想取消設置這些環境變量。
問題:我怎樣才能做到這一點?
不幸的是,在這種情況下,您不能使用Maven Surefire Plugin的environmentVariables
選項,主要是因為它只能添加新的環境變量,而不能覆蓋(或重置,實際上等於覆蓋為空值)現有變量。
另請注意:在 Maven 中包裝並在測試之前執行的ant run也不起作用。
建議的解決方案基於 Java,尤其是基於另一篇 SO 帖子中提出的這種方法。 盡管不建議用於應用程序代碼,但對於測試代碼,這種hack可能是可以接受的。
您可以將以下類添加到您的測試代碼中(在src/test/java
):
package com.sample;
import java.lang.reflect.Field;
import java.util.Map;
public class EnvHack {
@SuppressWarnings("unchecked")
public static void resetEnvironmentVariable(String name, String value) throws Exception {
Class<?> processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment");
Field theEnvironmentField = processEnvironmentClass.getDeclaredField("theEnvironment");
theEnvironmentField.setAccessible(true);
Map<String, String> env = (Map<String, String>) theEnvironmentField.get(null);
env.put(name, value);
Field theCaseInsensitiveEnvironmentField = processEnvironmentClass
.getDeclaredField("theCaseInsensitiveEnvironment");
theCaseInsensitiveEnvironmentField.setAccessible(true);
Map<String, String> cienv = (Map<String, String>) theCaseInsensitiveEnvironmentField.get(null);
cienv.put(name, value);
}
public static void main(String[] args) throws Exception {
resetEnvironmentVariable("test_prop", "test_value");
}
}
上面的類基本上是破解 Java API 以在內存中更改環境變量的值。 因此,它們可以設置為不同的值,實際上可以重置甚至取消設置(將其從地圖中刪除)。
由於該類現在是您的測試代碼的一部分,您有幾個選擇:
@Before
方法(或@BeforeClass
, 有一定區別)中使用該類(在相關類的每個 JUnit 方法之前)讓我們來看看每個可能的解決方案。
在某個 JUnit 測試用例的@Before
方法中使用該類
package com.sample;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class MainTest {
@Before
public void init() throws Exception {
EnvHack.resetEnvironmentVariable("test_prop", "test_value");
}
@Test
public void testEnvProperty() throws Exception {
String s = System.getenv("test_prop");
Assert.assertEquals(s, "test_value");
}
}
這個解決方案可以用於每個測試類,並且當一組測試(方法)共享相同的需求時(建議:如果它們沒有,它可能是一個提示,可能應該移除一些方法)。
在 JUnit 測試方法中使用它
package com.sample;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class MainTest {
@Before
public void init() throws Exception {
EnvHack.resetEnvironmentVariable("test_prop", "test_value");
}
@Test
public void testEnvProperty() throws Exception {
EnvHack.resetEnvironmentVariable("test_prop", "test_value2");
String s = System.getenv("test_prop");
Assert.assertEquals(s, "test_value2");
}
}
該解決方案提供了最高的自由度:您可以在需要的地方准確地使用相關變量,盡管可能會受到代碼重復的影響,但它也可以強制測試隔離。
在任何執行的 JUnit 測試之前運行它的 main 方法
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<phase>process-test-classes</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>com.sample.EnvHack</mainClass>
<classpathScope>test</classpathScope>
</configuration>
</execution>
</executions>
</plugin>
請注意我們在這種情況下所做的事情:
java
目標來實際調用我們的env hack類的mainClass
。classPathScope
設置為test
情況下調用它,以使其對 Enforcer 插件可見process-test-classes
階段的一部分運行,只是為了確保它在test
階段之前執行,因此在任何測試之前執行。該解決方案集中了整個准備環境過程,一次用於所有測試。
另一方面,您也可以考慮在測試中使用模擬。 這不是一個集中的選項(除非你編碼),但可以提供進一步的提示,因此值得一提。 這是通過 PowerMock 重置環境變量的示例代碼
package com.sample;
import org.junit.*;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PrepareForTest(System.class)
public class EnvTest {
@Before
public void init() {
PowerMockito.mockStatic(System.class);
Mockito.when(System.getenv("TEST_PROP")).thenReturn("TEST_VALUE");
}
@Test
public void test() {
String var = System.getenv("TEST_PROP");
Assert.assertEquals("TEST_VALUE", var);
}
}
這類似於上面提出的第一種和第二種方法。
請注意,要使其工作,您需要將以下依賴項添加到 POM:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-core</artifactId>
<version>1.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.5</version>
<scope>test</scope>
</dependency>
</dependencies>
一般注意事項:確實不建議進行未完全隔離且取決於環境變量存在(或不存在)的測試。 您可能會遇到維護問題或遇到更棘手的故障排除,無論是為同事還是為您自己的未來。 所以,如果你真的需要它,最好正確記錄它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.