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

标签 java junit mockito powermockito

在Java中,我有一个类,例如

public class A {

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

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

现在我需要在单元测试中以某种方式模拟这个全局变量。不幸的是,我被告知要避免出于测试目的对被测试类的源代码进行任何更改,特别是简单地提供 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 ”。我怀疑如果从全局变量的初始化中调用静态方法调用,则不可能以这种方式调用它们...有人知道是否有任何方法可以模拟此变量(正如我所说,无需更改类 A ) ?

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

嗯,我同意,通常模拟不可变的 map 没有多大意义,但实际上, map 看起来更像是这样的:

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

我真正需要的是模拟 B 类型的对象,这是值之一,因为它是通过 steps.get(...) 在类的其他方法中访问的。

最佳答案

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

关于java - JUnit:是否可以模拟在全局变量的初始化中调用的静态方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58372553/

相关文章:

java - 如何为无效返回方法定义 AnswersWithDelay

spring - ReflectionTestUtils 在 Spring 测试中不能与 @Autowired 一起使用

java - Mockito 测试抛出异常的 void 方法。 Spring Boot,eclipse IDE

java - 递归打印,没有任何循环

java - 从 maven 2 升级到 maven 3

java - 为什么 ExpectedException 在 Spring 中被弃用

java - 在 Eclipse 中运行 junit 测试用例时出错

java - CORS 过滤器不适用于 Java + angularjs

java - 选择 GQLQueries (JDO) Google app Engine JAVA 中的特定行

java - 使用 Hibernate ConstraintViolationException