Search code examples
javajunitmockitopowermockito

JUnit: Is it possible to mock a static method called within the initialization of a global variable?


In Java, I have a class like for example

public class A {

  private final Map<Integer, String> steps = ImmutableMap.of(
      1, "one"
  );

  public String getStepOne() {
    return steps.get(1);
  }
}

Now I need to somehow mock this global variable in a unit test. Unfortunately, I was told to avoid any changes in source code of the tested class for testing purposes, especially, simply providing a getter wouldn't be a satisfying solution. My attempt was to mock the static method call like

@RunWith(PowerMockRunner.class)
@PrepareForTest({A.class, ImmutableMap.class})
public class ATest {

  private A subj = new A();

  @Before
  public void setUp() {
    PowerMockito.mockStatic(ImmutableMap.class);
    ImmutableMap<Object, Object> mockedMap = ImmutableMap.of(1, "NEW ONE");
    BDDMockito.given(ImmutableMap.of()).willReturn(mockedMap);
  }

  @Test
  public void testGetStepOne() {
    System.out.println(subj.getStepOne());
  }
}

But this doesn't work, it prints "one" and not "NEW ONE". I suspect that mocking static method calls this way isn't possible if they are called from the initialization of a global variable ... does somebody know if there is any way to mock this variable (as I said, without changes in class A)?

============ EDIT ==================

Well, I agree that generally it does not make much sense to mock an immutable map, but actually, the map looks more like this:

  private final Map<Integer, B> steps = ImmutableMap.of(
      1, new B()
  );

and what I actually need, is to mock the object of type B, which is one of the values, because it is accessed in further methods of the class via steps.get(...).


Solution

  • A pure Java solution might be to use reflection in the @Before method. The trick is to get rid of the final property at first, and then to change the value. See the 1st answer of this: Change private static final field using Java reflection. Same should work for non static members. See the modified code from this post here: Java reflection example to change final member