JUnit:是否可以模拟在全局变量的初始化中调用的静态方法?

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

在 Java 中,我有一个 class 例如

public class A {

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

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

现在我需要在单元测试中以某种方式模拟这个全局变量。不幸的是,我被告知要避免出于测试目的而对被测 class 的源代码进行任何更改,尤其是简单地提供 getter 并不是一个令人满意的解决方案。 我的尝试是像

一样模拟静态方法调用
@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());
  }
}

但这不起作用,它打印“one”而不是“NEW ONE”。我怀疑如果从全局变量的初始化调用它们,那么以这种方式模拟静态方法调用是不可能的......有人知道是否有任何方法可以模拟这个变量(正如我所说, [=32 没有变化=] A)?

============编辑==================

好吧,我同意通常模拟不可变映射没有多大意义,但实际上,映射看起来更像这样:

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

而我真正需要的是模拟 B 类型的对象,它是值之一,因为它在 class 的进一步方法中通过 steps.get(...).

一个纯粹的 Java 解决方案可能是在 @Before 方法中使用反射。诀窍是首先摆脱 final 属性,然后再更改值。请参阅第一个答案:Change private static final field using Java reflection。同样适用于非静态成员。 在此处查看此 post 的修改代码:Java reflection example to change final member