請教下有沒有在 slb 或者 nginx 層面實施 mock 的開源框架,最好是 java 的
公司用的 nacos 做服務管理,還是 1.4 的老版本,同時還有一些老專案沒接 nacos 直接走 http 請求,測試目前有一套自研的 mock 工具,但是對程式碼有一些侵入,而且有些專案存在依賴不相容問題。
所以現在想一步到位在 ng 層面做 mock 解決所有問題,請教下各位大佬有沒有開源的 mock 框架,或者有沒有其他好的解決方案。
順便就分享下現用的 mock 工具,原理就是在被 mock 類上加註解,然後透過反射替換返回值或者請求到 mock 服務上。
主要實現 2 個功能:
- 根據配置中心的配置直接返回被 mock 方法返回值
- 根據環境將請求轉發到對應環境的 mock 服務,然後在 mock 服務裡面處理邏輯。
領導覺得太 low 了讓在 ng 層實現,所以希望有能在 ng 層實現上面倆功能的工具,求大佬們推薦。
@Aspect
public class ConfMockAspect {
@Autowired
SpelExcetor spelExcetor;
private final static Logger logger = LoggerFactory.getLogger(ConfMockAspect.class);
private static String mock_system_test_url = "http://xxxx";
private static String mock_system_dev_url = "http://xxxx";
@Pointcut("@within(com.mock.ConfMock)")
private void aspect() {}
@Around("aspect()")
public Object around(JoinPoint joinPoint) throws Throwable {
Object target = joinPoint.getTarget();
Class<?> targetClass = target.getClass();
Class<?>[] interfaces = targetClass.getInterfaces();
String sName = targetClass.getSimpleName();
MethodSignature sig = (MethodSignature)joinPoint.getSignature();
Method method = sig.getMethod();
String methodName = method.getName();
Type type = method.getGenericReturnType();
String key = "ConfMock." + sName + "." + methodName;
// 走mock系統
String sysKey1 = "system.ConfMock." + sName;
String sysKey2 = "system.ConfMock." + sName + "." + methodName;
String value = null;
if (LocalCacheRepository.getInstance().get(sysKey1) != null
|| LocalCacheRepository.getInstance().get(sysKey2) != null) {
String url = null;
if (PropertyConstant.CONF_PROD_DEV.equals(AppInstance.getEnv())) {
url = mock_system_dev_url + String.format("/api?className=%s&method=%s¶mClass=%s",
interfaces[0].getName(), methodName, method.getParameterTypes()[0].getName());
} else if (PropertyConstant.CONF_PROD_TEST.equals(AppInstance.getEnv())){
url = mock_system_test_url + String.format("/api?className=%s&method=%s¶mClass=%s",
interfaces[0].getName(), methodName, method.getParameterTypes()[0].getName());
} else {
url = mock_system_uat_url + String.format("/api?className=%s&method=%s¶mClass=%s",
interfaces[0].getName(), methodName, method.getParameterTypes()[0].getName());
}
String param = JSON.toJSONString(joinPoint.getArgs()[0], new LengthFilter());
value = HttpUtil.doPost(param, new HashMap<>(), url);
if (value != null) {
return JSON.parseObject(value, type);
}
} else {
value = getValue(joinPoint, key);
if (value != null) {
Object result = parseReturn(value, type, joinPoint.getArgs());
return result;
}
}
return ((ProceedingJoinPoint)joinPoint).proceed();
}
private String getValue(JoinPoint joinPoint, String key) {
try {
Properties properties = LocalCacheRepository.getInstance().getProperties();
Set<Object> set = properties.keySet();
for (Object srt : set) {
String keyStr = srt.toString();
if (keyStr.startsWith(key)) {
String s = org.apache.commons.lang3.StringUtils.removeStart(keyStr, key);
if (!StringUtils.isEmpty(s)) {
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setRootObject(joinPoint.getArgs());
Boolean result =
(Boolean)parser.parseExpression(org.apache.commons.lang3.StringUtils.removeStart(s, "."))
.getValue(context);
if (result) {
return properties.getProperty(keyStr);
}
}
}
}
if (properties.containsKey(key)) {
return properties.getProperty(key);
}
} catch (Exception e) {
logger.warn("解析key失敗", e);
}
return null;
}
private Object parseReturn(String value, Type type, Object[] args) {
if (String.class.getTypeName().equals(type.getTypeName())) {
return value;
}
Object object = JSON.parse(value);
if (object instanceof JSONArray) {
JSONArray array = (JSONArray)object;
parseValue(array, args);
return array.toJavaObject(type);
} else if (object instanceof JSONObject) {
JSONObject jsonObject = (JSONObject)object;
parseValue(jsonObject, args);
return jsonObject.toJavaObject(type);
}
return object;
}
private void parseValue(JSONArray array, Object rootObject) {
if (array != null && !array.isEmpty()) {
for (int i = 0; i < array.size(); i++) {
Object value = array.get(i);
if (value != null) {
if (value instanceof String) {
Object newValue = doneInSpringContext((String)value, rootObject);
if (newValue != null) {
array.set(i, newValue);
}
} else if (value instanceof JSONObject) {
parseValue((JSONObject)value, rootObject);
} else if (value instanceof JSONArray) {
parseValue((JSONArray)value, rootObject);
}
}
}
}
}
private void parseValue(JSONObject object, Object rootObject) {
Set<String> set = object.keySet();
if (!set.isEmpty()) {
for (String key : set) {
Object value = object.get(key);
if (value != null) {
if (value instanceof String) {
if (isSpel((String)value)) {
Object newValue = doneInSpringContext(spelValue((String)value), rootObject);
if (newValue != null) {
object.put(key, newValue);
}
}
} else if (value instanceof JSONObject) {
parseValue((JSONObject)value, rootObject);
} else if (value instanceof JSONArray) {
parseValue((JSONArray)value, rootObject);
}
}
}
}
}
private static boolean isSpel(String value) {
// ${}
if (value != null && value.startsWith("${") && value.endsWith("}")) {
return true;
}
return false;
}
public static String spelValue(String value) {
if (isSpel(value)) {
value = org.apache.commons.lang3.StringUtils.removeFirst(value, "\\$\\{");
value = org.apache.commons.lang3.StringUtils.removeEnd(value, "}");
return value;
}
return value;
}
private Object doneInSpringContext(String value, Object rootObject) {
try {
return spelExcetor.doneInSpringContext(null, rootObject, value);
} catch (Exception e) {
}
return null;
}
public static class LengthFilter implements ValueFilter{
@Override
public Object process(Object object, String name, Object value) {
if (value != null && value instanceof String) {
String var = (String)value;
if (var.length() > 500) {
return var.substring(0, 500);
}
}
return value;
}
}
相關文章
- 最好的 Go 框架:沒有框架?Go框架
- 請教:有什麼常用的 java_selenium 的自動化測試框架Java框架
- 淺談 Easy-mock 最好的備胎沒有之一Mock
- Jmeter 對 Java 請求的測試實施JMeterJava
- 在Java中,以下有關類的關聯關係描述錯誤的是()Java
- Java面試寶典之開源框架!Java面試框架
- 中小型企業有沒有實施ERP的必要?
- 沒有部署ingress pod的woker節點telnet slb的80 443埠不通
- java培訓沒有錯 錯的是你沒有好好學Java
- 有沒有和laravel一樣的golang框架!請推薦一下!LaravelGolang框架
- 想問一下有沒有采用 Laravel+Vue 的前後端分離的開源專案可以學習一下的啊?LaravelVue後端
- Java中的四層框架Java框架
- 這是道面試題,想不懂,請教大家面試題
- 請教 github.com/antonmedv/expr 有沒有人用過Github
- Mock 框架 Moq 的使用Mock框架
- android面試——開源框架的原始碼解析Android面試框架原始碼
- 有沒有開源的測試平臺可以參考的?
- 一種在 MediaWiki 頁面中引入 Vue 專案或者其他框架的辦法Vue框架
- Java 界最好用的開源行為驗證碼工具!Java
- 關於部落格開源計劃的實施
- 可能是最好用的Android引導層庫Android
- 【Java】留下沒有基礎眼淚的面試題Java面試題
- 想請教大家,平時使用者上傳的或者自己上傳的圖片檔案,是儲存到根目錄public裡還是storage裡面呢?
- 我剛開始學習java,我什麼也不懂,框架到底是什麼,沒有框架可以使用java嗎Java框架
- 我是怎樣學習新的語言或者框架的框架
- Android 面試開源框架篇Android面試框架
- 請教,topthink是基於onethink構建的嗎?
- 有哪些錯是Java程式設計師在面試中最容易犯的呢?Java程式設計師面試
- Nginx實現請求的負載均衡 + keepalived實現Nginx的高可用Nginx負載
- 最好用的開源日誌分析工具
- Nginx 軟體層面加強Nginx效能優化的面試問答和解決方案Nginx優化面試
- 【Java】留下沒有基礎眼淚的面試題,java初級面試筆試題Java面試題筆試
- 在事件中實現 佇列的時候報錯請教一下事件佇列
- Google官方Fragment頁面框架Navigation和XPage開源框架的使用對比GoFragment框架Navigation
- 你有沒有想過: 為什麼Java中String是不可變的?Java
- Java、Python到底誰是最好的程式語言?JavaPython
- 請教您關於 Nginx 下多個 Laravel 專案的部署問題NginxLaravel
- 最基礎的Nginx教學Nginx