PowerMockito+Junit - Mocking System.getenv

Gayathri picture Gayathri · Aug 23, 2018 · Viewed 10.3k times · Source

The line i try to mock in class is:

String x[] = System.getenv("values").split(",")
for(int i=0;i<=x.length;i++){
  //do something
}

As far I have written is as follows:

@RunWith(PowerMockRunner.class)
   @PrepareForTest({System.class})
   public class test{
           @Test
           public void junk(){

            PowerMockito.mockStatic(System.class);
            PowerMockito.when( System.getenv("values"))).thenReturn("ab,cd"); 
           }

         }

On debug, I get null pointer in for loop line. On inspecting System.getenv("values") in codebase, it is still found to be null

Please favour on the resolution

Edit: Exact issue replicable scenario:

package com.xyz.service.impl;

public class Junkclass {
    public String tests(){
        String xx[] = System.getenv("values").split(",");
        for (int i = 0; i < xx.length; i++) {
            return xx[i];
        }
        return null;
    }
}

package com.xyz.service.impl
@InjectMocks
@Autowired
Junkclass jclass;

@Test
    public void junk() {
        String x = "ab,cd";

        PowerMockito.mockStatic(System.class);

        // establish an expectation on System.getenv("values")
        PowerMockito.when(System.getenv("values")).thenReturn(x);

        // invoke System.getenv("values") and assert that your expectation was applied correctly
        Assert.assertEquals(x, System.getenv("values"));
        jclass.tests();

    }

Answer

glytching picture glytching · Aug 23, 2018

In your test case you are invoking System.getenv("values").split(",") but you haven't told PowerMock to return anything from System.getenv("values") so your code wil throw an NPE when it attempts to invoke split(",") on the null response from System.getenv("values").

The purpose of your test isn't clear to me but the following test will pass and it shows how to set an expectation on System.getenv("values"):

@Test
public void junk() {
    String input = "ab,cd";

    PowerMockito.mockStatic(System.class);

    // establish an expectation on System.getenv("values")
    PowerMockito.when(System.getenv("values")).thenReturn(input);

    // invoke System.getenv("values") and assert that your expectation was applied correctly
    Assert.assertEquals(input, System.getenv("values"));

    String x[] = System.getenv("values").split(",");
    for (int i = 0; i < x.length; i++) {
        System.out.println(x[i]);
    }
}

The above code will print out:

ab
cd

Update:

Based on the provision of the "exact scenario" in the above question, the following test will pass i.e. System.getenv("values") will return the mocked value when invoked in junkclass.tests() ...

@RunWith(PowerMockRunner.class)
@PrepareForTest({System.class, junkclass.class})
public class Wtf {

    @Test
    public void junk() {
        String x = "ab,cd";

        PowerMockito.mockStatic(System.class);

        // establish an expectation on System.getenv("values")
        PowerMockito.when(System.getenv("values")).thenReturn(x);

        // invoke System.getenv("values") and assert that your expectation was applied correctly
        Assert.assertEquals(x, System.getenv("values"));
        jclass.tests();
    }
}