12

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();

    }
Raedwald
  • 46,613
  • 43
  • 151
  • 237
Gayathri
  • 1,776
  • 5
  • 23
  • 50

1 Answers1

14

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();
    }
}
glytching
  • 44,936
  • 9
  • 114
  • 120
  • You're right .. But .. i have edited my question on behavior with the change you suggested. – Gayathri Aug 23 '18 at 07:48
  • I've updated the answer, the test in my answer successfully loops over the array of split values. Not sure exactly what exception you are seeing but it could be because the upper bound of the array in your code is 2, not 1. See the last part of my answer for clarification on this point. – glytching Aug 23 '18 at 07:55
  • 1
    When i inspected the value of System.getenv("values") in main code, i could still see it as null .. – Gayathri Aug 23 '18 at 07:59
  • Does the line being in a private method in another class have impact ? – Gayathri Aug 23 '18 at 08:25
  • I don't know. I've posted a test which shows the PowerMock calls working successfully. There is something about your use case which results in an unsuccessful outcome but it is not possible to reproduce that given the information in your question. Perhaps you could create a [MCVE](https://stackoverflow.com/help/mcve)? – glytching Aug 23 '18 at 08:28
  • I have added the exact scenario wherein i get null pointer exception. This is replicable. – Gayathri Aug 23 '18 at 09:35
  • 4
    You need to inlcude `junkclass` in `PrepareForTest` e.g. `@PrepareForTest({System.class, junkclass.class})` – glytching Aug 23 '18 at 09:43
  • doesn't junkclass require "@InjectMocks" and/or "@Autowired"? Coz I use Mockito as well in class. Junkclass is just an example. Actual class is a big one for which i use Mockito.when(...).thenReturn(..) – Gayathri Aug 23 '18 at 09:45
  • You saved me. Thanks loads!! – Gayathri Aug 23 '18 at 09:51
  • 5
    I am getting Mockito cannot mock/spy because --final class at System.class. I am wondering how did it work for you. Any suggestions? – esha Apr 12 '20 at 14:29