feat(接口测试): 修复部分Xml转JSON无法解析的问题

--bug=1016192 --user=宋天阳 【接口测试】tcp的mock请求,两个mock期望都返回了一个响应内容
https://www.tapd.cn/55049933/s/1232195
This commit is contained in:
song-tianyang 2022-08-24 13:40:11 +08:00 committed by 刘瑞斌
parent b787dc19c1
commit 698328ab7f
4 changed files with 63 additions and 47 deletions

View File

@ -94,7 +94,7 @@ public class TcpTreeTableDataParser {
boolean isMatch = false; boolean isMatch = false;
for (TcpTreeTableDataStruct dataStruct : tcpDataList) { for (TcpTreeTableDataStruct dataStruct : tcpDataList) {
if(isMatch){ if (isMatch) {
break; break;
} }
String key = dataStruct.getName(); String key = dataStruct.getName();
@ -111,16 +111,22 @@ public class TcpTreeTableDataParser {
} else if (sourceObjItem instanceof JSONArray) { } else if (sourceObjItem instanceof JSONArray) {
if (!CollectionUtils.isEmpty(dataStruct.getChildren())) { if (!CollectionUtils.isEmpty(dataStruct.getChildren())) {
JSONArray jsonArray = (JSONArray) sourceObjItem; JSONArray jsonArray = (JSONArray) sourceObjItem;
for (int i = 0; i < jsonArray.size(); i ++){ boolean hasMatchAny = false;
for (int i = 0; i < jsonArray.size(); i++) {
Object itemObj = jsonArray.get(i); Object itemObj = jsonArray.get(i);
if(itemObj instanceof JSONObject){ if (itemObj instanceof JSONObject) {
if (!isMatchTreeTableData((JSONObject) itemObj, dataStruct.getChildren())) { if (!isMatchTreeTableData((JSONObject) itemObj, dataStruct.getChildren())) {
continue; continue;
} else {
hasMatchAny = true;
} }
}else { } else {
continue; continue;
} }
} }
if (!hasMatchAny) {
continue;
}
} else { } else {
continue; continue;
} }
@ -134,8 +140,8 @@ public class TcpTreeTableDataParser {
continue; continue;
} }
} }
isMatch = true;
} }
isMatch = true;
} }
return isMatch; return isMatch;

View File

@ -104,7 +104,7 @@ public class MockApiUtils {
} else if (StringUtils.equalsIgnoreCase(type, "XML")) { } else if (StringUtils.equalsIgnoreCase(type, "XML")) {
if (bodyObj.containsKey("raw")) { if (bodyObj.containsKey("raw")) {
String xmlStr = bodyObj.getString("raw"); String xmlStr = bodyObj.getString("raw");
JSONObject matchObj = XMLUtils.stringToJSONObject(xmlStr); JSONObject matchObj = XMLUtils.xmlStringToJSONObject(xmlStr);
returnJson = matchObj; returnJson = matchObj;
} }
} else if (StringUtils.equalsIgnoreCase(type, "Raw")) { } else if (StringUtils.equalsIgnoreCase(type, "Raw")) {
@ -415,7 +415,7 @@ public class MockApiUtils {
return returnJson; return returnJson;
} else if (StringUtils.startsWithIgnoreCase(request.getContentType(), "text/xml")) { } else if (StringUtils.startsWithIgnoreCase(request.getContentType(), "text/xml")) {
String xmlString = readXml(request); String xmlString = readXml(request);
JSONObject object = XMLUtils.stringToJSONObject(xmlString); JSONObject object = XMLUtils.xmlStringToJSONObject(xmlString);
return object; return object;
} else if (StringUtils.startsWithIgnoreCase(request.getContentType(), "application/x-www-form-urlencoded")) { } else if (StringUtils.startsWithIgnoreCase(request.getContentType(), "application/x-www-form-urlencoded")) {
JSONObject object = new JSONObject(); JSONObject object = new JSONObject();
@ -655,6 +655,9 @@ public class MockApiUtils {
} }
public static boolean isValueMatch(String requestParam, MockConfigRequestParams params) { public static boolean isValueMatch(String requestParam, MockConfigRequestParams params) {
if (StringUtils.isBlank(params.getCondition())) {
params.setCondition(MockParamConditionEnum.VALUE_EQUALS.name());
}
if (StringUtils.equals(params.getCondition(), MockParamConditionEnum.VALUE_EQUALS.name())) { if (StringUtils.equals(params.getCondition(), MockParamConditionEnum.VALUE_EQUALS.name())) {
return StringUtils.equals(requestParam, params.getValue()); return StringUtils.equals(requestParam, params.getValue());
} else if (StringUtils.equals(params.getCondition(), MockParamConditionEnum.VALUE_NOT_EQUALS.name())) { } else if (StringUtils.equals(params.getCondition(), MockParamConditionEnum.VALUE_NOT_EQUALS.name())) {

View File

@ -24,7 +24,6 @@ import io.metersphere.base.mapper.ext.ExtMockExpectConfigMapper;
import io.metersphere.commons.constants.ProjectApplicationType; import io.metersphere.commons.constants.ProjectApplicationType;
import io.metersphere.commons.exception.MSException; import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.*; import io.metersphere.commons.utils.*;
import io.metersphere.jmeter.utils.ScriptEngineUtils;
import io.metersphere.i18n.Translator; import io.metersphere.i18n.Translator;
import io.metersphere.service.ProjectApplicationService; import io.metersphere.service.ProjectApplicationService;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
@ -41,7 +40,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*; import java.io.ByteArrayInputStream;
import java.util.*; import java.util.*;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -390,7 +389,7 @@ public class MockConfigService {
if (StringUtils.equalsAnyIgnoreCase(type, "Form Data", "WWW_FORM") && expectBodyObject.containsKey("kvs")) { if (StringUtils.equalsAnyIgnoreCase(type, "Form Data", "WWW_FORM") && expectBodyObject.containsKey("kvs")) {
JSONArray kvsArr = expectBodyObject.getJSONArray("kvs"); JSONArray kvsArr = expectBodyObject.getJSONArray("kvs");
List<MockConfigRequestParams> mockConfigRequestParams = MockApiUtils.getParamsByJSONArray(kvsArr); List<MockConfigRequestParams> mockConfigRequestParams = MockApiUtils.getParamsByJSONArray(kvsArr);
if(CollectionUtils.isNotEmpty(mockConfigRequestParams)){ if (CollectionUtils.isNotEmpty(mockConfigRequestParams)) {
if (!MockApiUtils.checkParamsCompliance(jsonArray, mockConfigRequestParams, StringUtils.equals(paramsFilterType, "And"))) { if (!MockApiUtils.checkParamsCompliance(jsonArray, mockConfigRequestParams, StringUtils.equals(paramsFilterType, "And"))) {
return false; return false;
} }
@ -705,7 +704,7 @@ public class MockConfigService {
return returnModel; return returnModel;
} }
public String updateHttpServletResponse(String projectId,MockExpectConfigResponse finalExpectConfig, String url, Map<String, String> headerMap, RequestMockParams requestMockParams, HttpServletResponse response) { public String updateHttpServletResponse(String projectId, MockExpectConfigResponse finalExpectConfig, String url, Map<String, String> headerMap, RequestMockParams requestMockParams, HttpServletResponse response) {
String returnStr = ""; String returnStr = "";
try { try {
//设置响应头和响应码 //设置响应头和响应码
@ -737,7 +736,7 @@ public class MockConfigService {
if (responseJsonObj.containsKey("usePostScript")) { if (responseJsonObj.containsKey("usePostScript")) {
useScript = responseJsonObj.getBoolean("usePostScript"); useScript = responseJsonObj.getBoolean("usePostScript");
} }
returnStr = mockApiUtils.getResultByResponseResult(projectId,responseJsonObj.getJSONObject("body"), url, headerMap, requestMockParams, useScript); returnStr = mockApiUtils.getResultByResponseResult(projectId, responseJsonObj.getJSONObject("body"), url, headerMap, requestMockParams, useScript);
} }
if (responseJsonObj.containsKey("httpCode")) { if (responseJsonObj.containsKey("httpCode")) {
int httpCodeNum = 500; int httpCodeNum = 500;
@ -998,18 +997,18 @@ public class MockConfigService {
JSON paramJson = MockApiUtils.getPostParamMap(request); JSON paramJson = MockApiUtils.getPostParamMap(request);
JSONObject parameterObject = MockApiUtils.getParameterJsonObject(request); JSONObject parameterObject = MockApiUtils.getParameterJsonObject(request);
for (ApiDefinitionWithBLOBs api : aualifiedApiList) { for (ApiDefinitionWithBLOBs api : aualifiedApiList) {
if(StringUtils.isEmpty(returnStr)){ if (StringUtils.isEmpty(returnStr)) {
RequestMockParams mockParams = MockApiUtils.getParams(urlSuffix, api.getPath(), parameterObject, paramJson, true); RequestMockParams mockParams = MockApiUtils.getParams(urlSuffix, api.getPath(), parameterObject, paramJson, true);
MockConfigResponse mockConfigData = this.findByApiId(api.getId()); MockConfigResponse mockConfigData = this.findByApiId(api.getId());
MockExpectConfigResponse finalExpectConfig = this.findExpectConfig(requestHeaderMap, mockConfigData.getMockExpectConfigList(), mockParams); MockExpectConfigResponse finalExpectConfig = this.findExpectConfig(requestHeaderMap, mockConfigData.getMockExpectConfigList(), mockParams);
if (finalExpectConfig != null) { if (finalExpectConfig != null) {
returnStr = this.updateHttpServletResponse(project.getId(),finalExpectConfig, url, requestHeaderMap, mockParams, response); returnStr = this.updateHttpServletResponse(project.getId(), finalExpectConfig, url, requestHeaderMap, mockParams, response);
}else { } else {
returnStr = this.getApiDefinitionResponse(api, response); returnStr = this.getApiDefinitionResponse(api, response);
} }
} }
} }
if(CollectionUtils.isNotEmpty(aualifiedApiList)){ if (CollectionUtils.isNotEmpty(aualifiedApiList)) {
matchApi = true; matchApi = true;
} }
} }
@ -1042,21 +1041,21 @@ public class MockConfigService {
JSONObject parameterObject = MockApiUtils.getParameterJsonObject(request); JSONObject parameterObject = MockApiUtils.getParameterJsonObject(request);
for (ApiDefinitionWithBLOBs api : aualifiedApiList) { for (ApiDefinitionWithBLOBs api : aualifiedApiList) {
if(StringUtils.isEmpty(returnStr)){ if (StringUtils.isEmpty(returnStr)) {
RequestMockParams paramMap = MockApiUtils.getParams(urlSuffix, api.getPath(), parameterObject, paramJson, false); RequestMockParams paramMap = MockApiUtils.getParams(urlSuffix, api.getPath(), parameterObject, paramJson, false);
MockConfigResponse mockConfigData = this.findByApiId(api.getId()); MockConfigResponse mockConfigData = this.findByApiId(api.getId());
if (mockConfigData != null && mockConfigData.getMockExpectConfigList() != null) { if (mockConfigData != null && mockConfigData.getMockExpectConfigList() != null) {
MockExpectConfigResponse finalExpectConfig = this.findExpectConfig(requestHeaderMap, mockConfigData.getMockExpectConfigList(), paramMap); MockExpectConfigResponse finalExpectConfig = this.findExpectConfig(requestHeaderMap, mockConfigData.getMockExpectConfigList(), paramMap);
if (finalExpectConfig != null) { if (finalExpectConfig != null) {
returnStr = this.updateHttpServletResponse(project.getId(),finalExpectConfig, url, requestHeaderMap, paramMap, response); returnStr = this.updateHttpServletResponse(project.getId(), finalExpectConfig, url, requestHeaderMap, paramMap, response);
}else { } else {
returnStr = this.getApiDefinitionResponse(api, response); returnStr = this.getApiDefinitionResponse(api, response);
} }
} }
} }
} }
if(CollectionUtils.isNotEmpty(aualifiedApiList)){ if (CollectionUtils.isNotEmpty(aualifiedApiList)) {
matchApi = true; matchApi = true;
} }
} }
@ -1076,7 +1075,7 @@ public class MockConfigService {
response.setStatus(responseDTO.getReturnCode()); response.setStatus(responseDTO.getReturnCode());
if (MapUtils.isNotEmpty(responseDTO.getHeaders())) { if (MapUtils.isNotEmpty(responseDTO.getHeaders())) {
for (Map.Entry<String, String> entry : responseDTO.getHeaders().entrySet()) { for (Map.Entry<String, String> entry : responseDTO.getHeaders().entrySet()) {
if(StringUtils.isNotEmpty(entry.getKey())){ if (StringUtils.isNotEmpty(entry.getKey())) {
response.setHeader(entry.getKey(), entry.getValue()); response.setHeader(entry.getKey(), entry.getValue());
} }
} }
@ -1134,11 +1133,17 @@ public class MockConfigService {
public MockExpectConfigDTO matchTcpMockExpect(String message, int port) { public MockExpectConfigDTO matchTcpMockExpect(String message, int port) {
ProjectApplicationExample pae = new ProjectApplicationExample(); ProjectApplicationExample pae = new ProjectApplicationExample();
pae.createCriteria().andTypeEqualTo(ProjectApplicationType.MOCK_TCP_OPEN.name()) pae.createCriteria().andTypeEqualTo(ProjectApplicationType.MOCK_TCP_PORT.name())
.andTypeValueEqualTo(String.valueOf(true));
pae.or().andTypeEqualTo(ProjectApplicationType.MOCK_TCP_PORT.name())
.andTypeValueEqualTo(String.valueOf(port)); .andTypeValueEqualTo(String.valueOf(port));
List<ProjectApplication> projectApplications = projectApplicationService.selectByExample(pae); List<ProjectApplication> projectApplicationsByMockTcpPort = projectApplicationService.selectByExample(pae);
List<ProjectApplication> projectApplications = new ArrayList<>();
for (ProjectApplication projectApp : projectApplicationsByMockTcpPort) {
pae.clear();
pae.createCriteria().andProjectIdEqualTo(projectApp.getProjectId())
.andTypeEqualTo(ProjectApplicationType.MOCK_TCP_OPEN.name())
.andTypeValueEqualTo(String.valueOf(true));
projectApplications.addAll(projectApplicationService.selectByExample(pae));
}
List<String> projectIds = projectApplications.stream().map(ProjectApplication::getProjectId).collect(Collectors.toList()); List<String> projectIds = projectApplications.stream().map(ProjectApplication::getProjectId).collect(Collectors.toList());
List<Project> projectList = new ArrayList<>(); List<Project> projectList = new ArrayList<>();
if (CollectionUtils.isNotEmpty(projectIds)) { if (CollectionUtils.isNotEmpty(projectIds)) {
@ -1176,12 +1181,14 @@ public class MockConfigService {
} }
} else if (isXMLMessage && StringUtils.equalsIgnoreCase(reportType, "xml")) { } else if (isXMLMessage && StringUtils.equalsIgnoreCase(reportType, "xml")) {
if (requestJson.containsKey("xmlDataStruct")) { if (requestJson.containsKey("xmlDataStruct")) {
JSONObject sourceObj = XMLUtils.XmlToJson(message); JSONObject sourceObj = XMLUtils.xmlStringToJSONObject(message);
try { if (!sourceObj.isEmpty()) {
List<TcpTreeTableDataStruct> tcpDataList = JSONArray.parseArray(requestJson.getString("xmlDataStruct"), TcpTreeTableDataStruct.class); try {
isMatch = TcpTreeTableDataParser.isMatchTreeTableData(sourceObj, tcpDataList); List<TcpTreeTableDataStruct> tcpDataList = JSONArray.parseArray(requestJson.getString("xmlDataStruct"), TcpTreeTableDataStruct.class);
} catch (Exception e) { isMatch = TcpTreeTableDataParser.isMatchTreeTableData(sourceObj, tcpDataList);
LogUtil.error(e); } catch (Exception e) {
LogUtil.error(e);
}
} }
} }
} else if (StringUtils.equalsIgnoreCase(reportType, "raw")) { } else if (StringUtils.equalsIgnoreCase(reportType, "raw")) {

View File

@ -4,14 +4,14 @@ import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import io.metersphere.performance.parse.EngineSourceParserFactory; import io.metersphere.performance.parse.EngineSourceParserFactory;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.dom4j.Attribute;
import org.dom4j.Document; import org.dom4j.Document;
import org.dom4j.Element; import org.dom4j.Element;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.util.*; import java.util.*;
import java.util.regex.*; import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class XMLUtils { public class XMLUtils {
@ -170,7 +170,7 @@ public class XMLUtils {
} }
} }
public static JSONObject stringToJSONObject(String xml) { public static JSONObject xmlStringToJSONObject(String xml) {
try { try {
return elementToJSONObject(stringToDocument(xml).getRootElement()); return elementToJSONObject(stringToDocument(xml).getRootElement());
} catch (Exception e) { } catch (Exception e) {
@ -181,22 +181,22 @@ public class XMLUtils {
public static JSONObject elementToJSONObject(Element node) { public static JSONObject elementToJSONObject(Element node) {
JSONObject result = new JSONObject(); JSONObject result = new JSONObject();
// 当前节点的名称文本内容和属性
List<Attribute> listAttr = node.attributes();// 当前节点的所有属性的list
for (Attribute attr : listAttr) {// 遍历当前节点的所有属性
result.put(attr.getName(), attr.getValue());
}
// 递归遍历当前节点所有的子节点
List<Element> listElement = node.elements();// 所有一级子节点的list List<Element> listElement = node.elements();// 所有一级子节点的list
if (!listElement.isEmpty()) { if (!listElement.isEmpty()) {
JSONArray jsonArray = new JSONArray();
for (Element e : listElement) {// 遍历所有一级子节点 for (Element e : listElement) {// 遍历所有一级子节点
if (e.attributes().isEmpty() && e.elements().isEmpty()) // 判断一级节点是否有属性和子节点 JSONObject jsonObject = elementToJSONObject(e);
result.put(e.getName(), e.getTextTrim());// 沒有则将当前节点作为上级节点的属性对待 jsonArray.add(jsonObject);
else { }
if (!result.containsKey(e.getName())) // 判断父节点是否存在该一级节点名称的属性 if (jsonArray.size() == 1) {
result.put(e.getName(), new JSONArray());// 没有则创建 result.put(node.getName(), jsonArray.getJSONObject(0));
((JSONArray) result.get(e.getName())).add(elementToJSONObject(e));// 将该一级节点放入该节点名称的属性对应的值中 } else {
} result.put(node.getName(), jsonArray);
}
} else {
if (!StringUtils.isAllBlank(node.getName(), node.getText())) {
result.put(node.getName(), node.getText());
} }
} }
return result; return result;