Mockito原理剖析—PowerMockito Mock静态方法原理、如何抑制静态初始化
程序员文章站
2022-04-27 10:58:17
...
PowerMockito如何进行静态类的Mock
核心相关类
org.powermock.core.classloader.javassist.JavassistMockClassLoader
org.powermock.core.transformers.javassist.InstrumentMockTransformer
流程
PowerMockito通过自定义ClassLoader
,在加载类之前,修改字节码中方法调用方的调用入口—将方法调用委托至MockGateway,从而实现方法拦截。
MockGateway
几种状态说明
状态 | 说明 |
---|---|
PROCEED | 进行实际的调用 |
SUPPRESS | 对于Field,返回默认值 对于Method,抑制方法调用 |
几种方法说明
方法 | 说明 |
---|---|
newInstanceCall | 用于替换new {Class}(...) 类型调用 |
fieldCall | 用于替换dot access 的属性访问 |
staticConstructorCall | 用于替换静态初始化函数调用 |
constructorCall | 用于替换构造函数调用 |
methodCall | 用于替换普通方法调用 |
代码修改示例:
修改前
package powermock;
/**
* @author lidelin.
*/
public class StaticMethodProvider {
static {
System.out.println("static init");
}
public static void provide() {
System.out.println("ok");
}
}
修改后
package powermock;
import java.io.PrintStream;
import javassist.runtime.Desc;
import org.powermock.core.MockGateway;
import org.powermock.core.classloader.PowerMockModified;
public class StaticMethodProvider implements PowerMockModified {
public StaticMethodProvider() {
}
public static void provide() {
Object var0 = MockGateway.methodCall(Desc.getClazz("powermock.StaticMethodProvider"), "provide", new Object[0], Desc.getParams("()"), "");
if (var0 == MockGateway.PROCEED) {
var0 = null;
PrintStream var1 = null;
Object var2 = MockGateway.fieldCall(var0, Desc.getClazz("java.lang.System"), "out", Desc.getType("Ljava/io/PrintStream;"));
if (var2 == MockGateway.PROCEED) {
var1 = System.out;
} else {
var1 = (PrintStream)var2;
}
PrintStream var10000 = var1;
String var6 = "ok";
PrintStream var5 = var10000;
Object var3 = null;
if (var5 != null) {
var3 = var5;
} else {
var3 = Desc.getClazz("java.io.PrintStream");
}
Object var4 = MockGateway.methodCall(var3, "println", new Object[]{var6}, Desc.getParams("(Ljava/lang/String;)V"), "");
if (var4 == MockGateway.PROCEED) {
var5.println(var6);
var2 = null;
}
}
}
static {
PrintStream var0 = null;
PrintStream var1 = null;
Object var2 = MockGateway.fieldCall(var0, Desc.getClazz("java.lang.System"), "out", Desc.getType("Ljava/io/PrintStream;"));
if (var2 == MockGateway.PROCEED) {
var1 = System.out;
} else {
var1 = (PrintStream)var2;
}
PrintStream var10000 = var1;
String var5 = "static init";
var0 = var10000;
Object var3 = null;
if (var0 != null) {
var3 = var0;
} else {
var3 = Desc.getClazz("java.io.PrintStream");
}
Object var4 = MockGateway.methodCall(var3, "println", new Object[]{var5}, Desc.getParams("(Ljava/lang/String;)V"), "");
if (var4 == MockGateway.PROCEED) {
var0.println(var5);
var2 = null;
}
}
}
如何抑制静态初始化
org.powermock.core.transformers.javassist.SuppressStaticInitializerMockTransformer
通过ClassLoader
加载类时,使用ClassTransformer
将静态初始化域替换为空方法
Note:这会导致静态Field无法被初始化
上一篇: javascript函数式编程实例分析_javascript技巧
下一篇: Mockito学习笔记