7

I'm trying to write a unit test with junit and mockito (very new to this) for a Spring Boot application. Basically in my code, I have specified an environment variable for a specific URL in a manifest.yml file (for deployment) that I can access through String URL = System.getenv("VARIABLE") in my code. I'm having a lot of trouble with my unit testing however, since the URL variable is obviously undefined. I tried the solution here, but realized this is only for mocking an environment variable if you're calling it from the actual test itself, not if you're relying on the environment variable being accessible from the code.

Is there any way to set it up so that when the test is run, I can set environment variables that can be accessed within the code?

PCR
  • 265
  • 1
  • 5
  • 14

3 Answers3

5

You can use PowerMockito to mock static methods. This code demonstrates mocking the System class and stubbing getenv()

@RunWith(PowerMockRunner.class)
@PrepareForTest({System.class})
public class Xxx {

    @Test
    public void testThis() throws Exception {
        System.setProperty("test-prop", "test-value");
        PowerMockito.mockStatic(System.class);

        PowerMockito.when(System.getenv(Mockito.eq("name"))).thenReturn("bart");
        // you will need to do this (thenCallRealMethod()) for all the other methods
        PowerMockito.when(System.getProperty(Mockito.any())).thenCallRealMethod();

        Assert.assertEquals("bart", System.getenv("name"));
        Assert.assertEquals("test-value", System.getProperty("test-prop"));
    }
}

I believe this illustrates what you are trying to accomplish. There may be a more elegant way to do this using PowerMockito.spy(), I just can't remember it.

You will need to do thenCallRealMethod() for all the other methods in System.class that get called directly or indirectly by your code.

StvnBrkdll
  • 3,924
  • 1
  • 24
  • 31
  • Hey I don't need the environment variable in the test itself, I just need it so that when the test itself runs the piece of code with the environment variable, it will be defined to whatever I set it. B/c right now yes, it is defined in the test, but when the test executes the actual code it is testing, it is undefined. – PCR Sep 19 '17 at 16:43
  • Understood, the code I added just demos the fact that System.getenv("name") returns the expected value. When your non-unit-test code calls System.getenv(), you will see similar results (i.e. mocking System will continue to work in your non-unit-test code). So, in your unit test, have line(s) like: `PowerMockito.when(System.getenv(Mockito.eq("name"))).thenReturn("bart");` to setup your environment. Your non-unit-test code should then see those values – StvnBrkdll Sep 19 '17 at 16:45
  • If this doesn't work, post back the problem and I can probably help you with it. – StvnBrkdll Sep 19 '17 at 17:15
  • Hey it's working, but it's causing another error in my unit test. I'm getting the following error `java.lang.ExceptionInInitializerError: null at java.lang.Integer.parseInt(Integer.java:454)` Will this interfere with other System calls? – PCR Sep 19 '17 at 17:31
  • Yes, we have mocked System, and what we need to do is "spy" System (also known as a partial mock). Give me a minute and I'll help you with the code. – StvnBrkdll Sep 19 '17 at 17:38
0

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

You have a couple of options:

EnvironmentVariables environmentVariables = new EnvironmentVariables("VARIABLE", "http://testurl");

// then put the test code inside an execute method
environmentVariables.execute(() -> {
   // inside here, the VARIABLE will contain the test value
});

// out here, the system variables are back to normal

Or it can be done with a JUnit4 or 5 plugin:

@ExtendWith(SystemStubsExtension.class)
class SomeTest {

    @SystemStub
    private EnvironmentVariables environment = new EnvironmentVariables("VARIABLE", "http://testurl");

    @Test
    void someTest() {
        // inside the test the variable is set
        // we can also change environment variables:

        environment.set("OTHER", "value");
    }

}
Ashley Frieze
  • 4,993
  • 2
  • 29
  • 23
0

Make the below changes to your pom.xml:

<dependency>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.22.2</version>
  <configuration>
   <environmentVariables>
      <PROPERTY_NAME>PROPERTY_VALUE</PROPERTY_NAME>
   </environmentVariables>
  </configuration>
</dependency>

Detailed answer can be found here.

Andreas Violaris
  • 2,465
  • 5
  • 13
  • 26