25

i am working on Junit5 . My java code uses the System.getenv("demoVar") to access environment variable . so how do i set up this environment variable in the jUnit5 test class , so that my code can access the value of this environment variable during the test.

ashish choudhary
  • 291
  • 1
  • 3
  • 7
  • 3
    Why has it been marked as duplicated? The answer in the duplicate question is about Java System Properties. This one is about environment variables. System.getenv is completly different that System.getProperty. Try to use System.setEnv("", "") !! :) So that response is not valid for this question. The right response should be an alternative for system-rules in JUnit5 – angelcervera Oct 24 '19 at 11:15
  • this is clearly not a duplicate as mentioned by @angelcervera – andgalf Dec 18 '19 at 11:02
  • 3
    With Java 8, you could change your method that calls System.getenv() so that it uses a Function instead. In your production code, you would use System::getenv, and in your test code, you can use Map::get on an internal map that you filled with test values. – Matthias Bohlen Mar 03 '20 at 15:42

5 Answers5

16

From this other SO answer https://stackoverflow.com/a/59635733/2185719:

There is JUnit Pioneer, a "JUnit 5 extension pack".

jUnit Pioneer offers an annotation that sets environment variables for a test. For example:

@Test
@SetEnvironmentVariable(key = "PATH", value = "")
void testPath_isEmpty() {
    assertThat(System.getenv("PATH")).isEmpty();
}
Miguel Ferreira
  • 1,282
  • 11
  • 27
  • 6
    This would give a warning from JDK9-16 and throws InaccessibleObjectException in JDK17. – Bala Sep 06 '22 at 12:53
  • 5
    There's an issue in the library's repository discussing the warnings and errors around using this annotation. It also offers ways to work around it. https://github.com/junit-pioneer/junit-pioneer/issues/509 – Miguel Ferreira Sep 09 '22 at 11:26
  • Thanks for the info @Miguel Ferreira. (They are still work arounds, we are planning to remove env variable dependency instead of using the work arounds). Thanks again for your time – Bala Sep 12 '22 at 13:52
  • @Bala Pioneer dedicated an entire section to this "issue": https://junit-pioneer.org/docs/environment-variables/#warnings-for-reflective-access – beatngu13 Nov 14 '22 at 19:58
7

You can't within the actual java process because these environmental values using getenv are immutable.

One way would be to start another vm or another process where you could introduce your new environment value.

Another way would be to switch to System.getProperty, but be sure you understand the differences.

https://www.baeldung.com/java-system-get-property-vs-system-getenv

Here is a little testcode:

public class EnvironmentVarsTest {
    private static int counter = 0;

    @BeforeEach
    public void setUp() {
        counter = counter + 1;
        System.setProperty("simple_test_env_property", String.valueOf(counter));
    }

    @Test
    public void testFirst() {
        printOutValues();
    }

    @Test
    public void testSecond() {
        printOutValues();
    }

    private void printOutValues() {
        System.out.println("--------------------");
        System.out.println("val=" + counter);
        System.out.println("envval=" + System.getProperty("simple_test_env_property"));
    }

}
wumpz
  • 8,257
  • 3
  • 30
  • 25
  • 1
    There is a [hack](https://stackoverflow.com/a/7201825/74334) that lets you set environment variables for the current process from Java code. It's not pretty and you shouldn't use it unless you really need it. On the other hand, Java should really have a proper method to do this without resorting to hacks. – sigint Aug 09 '19 at 12:22
  • Note: there are libraries that let you do this easily. However, from Java 16 onwards, the reflection hacks no longer work. https://github.com/webcompere/system-stubs has a mockito-based solution to this which does work. – Ashley Frieze Jan 20 '22 at 15:25
3

This can be achieved with https://github.com/webcompere/system-stubs/tree/master/system-stubs-jupiter


@ExtendWith(SystemStubsExtension.class)
class TestClass {

    @SystemStub
    private EnvironmentVariables environmentVariables =
        new EnvironmentVariables("demoVar", "val");

    @Test
    void test() {
        // can use the environment
        assertThat(System.getenv("demoVar")).isEqualTo("val");

        // can also change the environment
        environmentVariables.set("foo", "bar");

        // environment variables restored to previous state when
        // test ends
    }
}
Ashley Frieze
  • 4,993
  • 2
  • 29
  • 23
1

Simple solution if you use Gradle, you can add following to your build.gradle

test {
  environment "ENV_VAR_NAME", "ENV_VAR_VALUE"
}

Link to Gradle doc: https://docs.gradle.org/current/dsl/org.gradle.api.tasks.testing.Test.html#org.gradle.api.tasks.testing.Test:environment

user2455862
  • 585
  • 10
  • 26
0

The common practice is to use System properties instead of environment variables. In this case you will run your java/maven/gradle command or whatever you use to run your tests with option -D demoVar="{your_value}". for maven goal:

 maven clean install -DdemoVar="test"

for java jar:

 java -jar xxx.jar -DdemoVar="test"

You will be able to get it from code with System.getProperty("demoVar").

If you really need to use environment variable, use OS functionality. For linux:

demoVar="test" mvn clean install

For windows PowerShell:

$env:demoVar = 'test'; mvn clean install
Eduard Dubilyer
  • 991
  • 2
  • 10
  • 21