1

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

DanielBK
  • 892
  • 8
  • 23
  • If this map is something that needs to be changed, redesign the `A` class so that you can change it. Otherwise, don't mock something that can't actually be changed in production code. – Andy Turner Oct 14 '19 at 08:12
  • @AndyTurner, thanks for replying, I added an edit to the question, please see. – DanielBK Oct 14 '19 at 08:26

1 Answers1

1

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

geri
  • 346
  • 2
  • 6