使用 PowerMockito 模拟静态方法

Mocking Static method using PowerMockito

我正在使用 PowerMockito 模拟静态方法以获得更好的行覆盖率。测试通过,但 Cobertura 仍将 return 行显示为红色。我不确定我是否以错误的方式使用 PowerMockito。有什么线索吗?

MUT

 public static Object getBean( String beanName ) {
    return AppContext.getApplicationContext().getBean( beanName );
}

联合测试

@RunWith ( PowerMockRunner.class )
@PrepareForTest ( {AppContext.class} )

private ApplicationContext applicationContext;

@Test
public void testGetBean() throws Exception {
    String beanName = "junitBean";
    applicationContext = Mockito.mock(ApplicationContext.class);

    PowerMockito.mockStatic(AppContext.class);

    AppContext.setApplicationContext(applicationContext);
    PowerMockito.when(AppContext.getApplicationContext()).thenReturn(applicationContext);
    PowerMockito.when(AppContext.getApplicationContext().getBean(beanName)).thenReturn(Object.class);

    AppContext.getBean(beanName);
}

要模拟静态方法,PowerMock 必须在编译后修改 class 的 Java 字节码。代码覆盖工具以相同的方式工作——它们 "instrument"(google for "bytecode instrumentation")字节码以收集关于哪些代码行被 运行.

鉴于这里有两个东西根据自己的需要修改已经编译好的代码,所以它们不能很好地协同工作也就不足为奇了。事实上,其他覆盖工具也有同样的问题,例如this issue 在 PowerMock GitHub 页面上。

正是出于这样的原因,模拟静态方法是一个坏主意,只有在非常特殊的情况下才应该这样做。在大多数情况下,您可以将静态方法调用包装在接口中并将接口的实例传递给被测对象,或者更好的是(如果代码在您的控制之下)删除静态方法并将其替换为实例方法。

您也可以将 ApplicationContext 实例直接传递到您正在测试的 class 的构造函数中。