采用ognl进行mock方法的匹配,如果只想对指定参数进行mock就配置ognl表达式
+ *
+ * @作者 尹吉欢
+ * @个人微信 jihuan900
+ * @微信公众号 猿天地
+ * @GitHub https://github.com/yinjihuan
+ * @作者介绍 http://cxytiandi.com/about
+ * @时间 2022-05-10 21:54
+ */
+public class MethodInvokeFilter {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MockClassFileTransformer.class);
+
+ public static boolean filter(Object[] args, String express) {
+ if (args.length == 0 || StringUtils.isBlank(express)) {
+ return true;
+ }
+
+ Express ex = ExpressFactory.getExpress(args);
+ for (int i = 0; i < args.length; i++) {
+ ex.bind("p" + i, args[i]);
+ }
+
+ try {
+ return ex.is(express);
+ } catch (OgnlExpressException e) {
+ LOG.error("ognl filter exception", e);
+ }
+
+ return false;
+ }
+}
diff --git a/fox-mock-agent/src/main/java/com/cxytiandi/foxmock/agent/transformer/MockClassFileTransformer.java b/fox-mock-agent/src/main/java/com/cxytiandi/foxmock/agent/transformer/MockClassFileTransformer.java
index 71977ff..72d760c 100644
--- a/fox-mock-agent/src/main/java/com/cxytiandi/foxmock/agent/transformer/MockClassFileTransformer.java
+++ b/fox-mock-agent/src/main/java/com/cxytiandi/foxmock/agent/transformer/MockClassFileTransformer.java
@@ -3,9 +3,11 @@
import com.alibaba.arthas.deps.org.slf4j.Logger;
import com.alibaba.arthas.deps.org.slf4j.LoggerFactory;
import com.cxytiandi.foxmock.agent.model.ClassInfo;
+import com.cxytiandi.foxmock.agent.model.MockInfo;
import com.cxytiandi.foxmock.agent.storage.StorageHelper;
+import com.cxytiandi.foxmock.agent.utils.JsonUtils;
import com.cxytiandi.foxmock.agent.utils.StringUtils;
-import com.google.gson.Gson;
+import javassist.CannotCompileException;
import javassist.CtClass;
import javassist.CtMethod;
@@ -59,17 +61,15 @@ public byte[] transform(ClassLoader loader, String className, Class> classBein
String data = StorageHelper.get(key);
if (Objects.nonNull(data)) {
match = true;
+ MockInfo mockInfo = null;
LOG.info(String.format("mock methods %s, mock data is %s", key, data));
- if (data.startsWith("throw new")) {
- String mockCode = "if(true){%s}";
- method.insertBefore(String.format(mockCode, data));
+ if (data.contains("f_mock_data") || data.contains("f_ognl_express")) {
+ mockInfo = JsonUtils.fromJson(data, MockInfo.class);
} else {
- String mockCode = "if(true){" +
- "return ($r)com.cxytiandi.foxmock.agent.utils.JsonUtils.parse(%s,%s,%s);" +
- "}";
- method.insertBefore(String.format(mockCode, new Gson().toJson(data), "\""+className+"\"", "\""+methodName+"\""));
+ mockInfo = new MockInfo();
+ mockInfo.setMockData(data);
}
-
+ updateMethod(mockInfo, method, className, methodName);
}
}
@@ -85,4 +85,16 @@ public byte[] transform(ClassLoader loader, String className, Class> classBein
throw new RuntimeException("transform error " + className, e);
}
}
+
+ private void updateMethod(MockInfo mockInfo, CtMethod method, String className, String methodName) throws CannotCompileException {
+ if (mockInfo.getMockData().startsWith("throw new")) {
+ String mockCode = "if(com.cxytiandi.foxmock.agent.transformer.MethodInvokeFilter.filter($args,%s)){%s}";
+ method.insertBefore(String.format(mockCode, JsonUtils.toJson(mockInfo.getOgnlExpress()), mockInfo.getMockData()));
+ } else {
+ String mockCode = "if(com.cxytiandi.foxmock.agent.transformer.MethodInvokeFilter.filter($args,%s)){" +
+ "return ($r)com.cxytiandi.foxmock.agent.utils.JsonUtils.parse(%s,%s,%s);" +
+ "}";
+ method.insertBefore(String.format(mockCode, JsonUtils.toJson(mockInfo.getOgnlExpress()), JsonUtils.toJson(mockInfo.getMockData()), "\""+className+"\"", "\""+methodName+"\""));
+ }
+ }
}
diff --git a/fox-mock-agent/src/main/java/com/cxytiandi/foxmock/agent/utils/JsonUtils.java b/fox-mock-agent/src/main/java/com/cxytiandi/foxmock/agent/utils/JsonUtils.java
index 98d9df6..aec96ae 100644
--- a/fox-mock-agent/src/main/java/com/cxytiandi/foxmock/agent/utils/JsonUtils.java
+++ b/fox-mock-agent/src/main/java/com/cxytiandi/foxmock/agent/utils/JsonUtils.java
@@ -16,6 +16,10 @@
*/
public class JsonUtils {
+ private static Gson gson = new Gson();
+
+ private JsonUtils() {}
+
public static Object parse(String data, String className, String methodName) {
try {
Type genericReturnType = null;
@@ -28,11 +32,18 @@ public static Object parse(String data, String className, String methodName) {
}
}
- Gson gson = new Gson();
Object value = gson.fromJson(data, genericReturnType);
return value;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
+
+ public static String toJson(Object src) {
+ return gson.toJson(src);
+ }
+
+ public static