refactor(接口测试): 优化mock执行匹配

This commit is contained in:
wxg0103 2024-05-11 12:29:23 +08:00 committed by Craftsman
parent 23fddfc8dd
commit a8af24681d
5 changed files with 39 additions and 27 deletions

View File

@ -5,7 +5,6 @@ import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.XMLUtils; import io.metersphere.sdk.util.XMLUtils;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import lombok.Data; import lombok.Data;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.List; import java.util.List;
@ -119,9 +118,6 @@ public class BodyParamMatchRule {
} }
private boolean matchObject(Object mockRule, Object requestParam) { private boolean matchObject(Object mockRule, Object requestParam) {
if (ObjectUtils.anyNull(mockRule, requestParam)) {
return false;
}
if (mockRule instanceof List<?> && requestParam instanceof List<?>) { if (mockRule instanceof List<?> && requestParam instanceof List<?>) {
List<Object> mockList = (List<Object>) mockRule; List<Object> mockList = (List<Object>) mockRule;

View File

@ -19,6 +19,8 @@ public class HttpRequestParam {
private LinkedHashMap<String, String> bodyParamsObj; private LinkedHashMap<String, String> bodyParamsObj;
private byte[] binaryParamsObj;
private String paramType; private String paramType;
//JSONArray JSONObject //JSONArray JSONObject

View File

@ -8,6 +8,8 @@ import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map; import java.util.Map;
//mock匹配规则 //mock匹配规则
@ -56,6 +58,8 @@ public class MockMatchRule implements Serializable {
keyValueMatchRule formDataBodyRule = new keyValueMatchRule(); keyValueMatchRule formDataBodyRule = new keyValueMatchRule();
if (formDataBody != null) { if (formDataBody != null) {
formDataBodyRule.setMatchAll(formDataBody.isMatchAll()); formDataBodyRule.setMatchAll(formDataBody.isMatchAll());
List<KeyValueInfo> matchRules = new ArrayList<>();
formDataBodyRule.setMatchRules(matchRules);
formDataBody.getMatchRules().stream() formDataBody.getMatchRules().stream()
.filter(keyValueInfo -> StringUtils.isNotBlank(keyValueInfo.getKey())) .filter(keyValueInfo -> StringUtils.isNotBlank(keyValueInfo.getKey()))
.forEach(keyValueInfo -> { .forEach(keyValueInfo -> {

View File

@ -4,10 +4,7 @@ import io.metersphere.api.domain.*;
import io.metersphere.api.dto.ApiFile; import io.metersphere.api.dto.ApiFile;
import io.metersphere.api.dto.definition.HttpResponse; import io.metersphere.api.dto.definition.HttpResponse;
import io.metersphere.api.dto.definition.ResponseBody; import io.metersphere.api.dto.definition.ResponseBody;
import io.metersphere.api.dto.mockserver.ApiMockConfigDTO; import io.metersphere.api.dto.mockserver.*;
import io.metersphere.api.dto.mockserver.BodyParamMatchRule;
import io.metersphere.api.dto.mockserver.HttpRequestParam;
import io.metersphere.api.dto.mockserver.MockResponse;
import io.metersphere.api.dto.request.http.MsHeader; import io.metersphere.api.dto.request.http.MsHeader;
import io.metersphere.api.dto.request.http.body.BinaryBody; import io.metersphere.api.dto.request.http.body.BinaryBody;
import io.metersphere.api.dto.request.http.body.Body; import io.metersphere.api.dto.request.http.body.Body;
@ -65,7 +62,7 @@ public class MockServerService {
} }
public ResponseEntity<?> execute(String method, String projectNum, String apiNum, HttpServletRequest request){ public ResponseEntity<?> execute(String method, String projectNum, String apiNum, HttpServletRequest request) {
var requestHeaderMap = MockServerUtils.getHttpRequestHeader(request); var requestHeaderMap = MockServerUtils.getHttpRequestHeader(request);
String url = request.getRequestURL().toString(); String url = request.getRequestURL().toString();
String requestUrlSuffix = MockServerUtils.getUrlSuffix(StringUtils.joinWith("/", "/mock-server", projectNum, apiNum), request); String requestUrlSuffix = MockServerUtils.getUrlSuffix(StringUtils.joinWith("/", "/mock-server", projectNum, apiNum), request);
@ -127,18 +124,16 @@ public class MockServerService {
ApiDefinitionMockConfigExample mockConfigExample = new ApiDefinitionMockConfigExample(); ApiDefinitionMockConfigExample mockConfigExample = new ApiDefinitionMockConfigExample();
mockConfigExample.createCriteria().andIdIn(apiDefinitionMockList.stream().map(ApiDefinitionMock::getId).collect(Collectors.toList())); mockConfigExample.createCriteria().andIdIn(apiDefinitionMockList.stream().map(ApiDefinitionMock::getId).collect(Collectors.toList()));
List<ApiDefinitionMockConfig> mockConfigs = apiDefinitionMockConfigMapper.selectByExampleWithBLOBs(mockConfigExample); List<ApiDefinitionMockConfig> mockConfigs = apiDefinitionMockConfigMapper.selectByExampleWithBLOBs(mockConfigExample);
// 寻找匹配的 ApiDefinitionMockConfig // 寻找匹配的 ApiDefinitionMockConfig
ApiDefinitionMockConfig apiDefinitionMockConfig = mockConfigs.stream() ApiDefinitionMockConfig apiDefinitionMockConfig = mockConfigs.stream()
.filter(mockConfig -> MockServerUtils.matchMockConfig(mockConfig.getMatching(), requestHeaderMap, param)) .filter(mockConfig -> MockServerUtils.matchMockConfig(mockConfig.getMatching(), requestHeaderMap, param))
.findFirst() .findFirst()
.orElse(null); .orElse(null);
// 如果是binary类型的body需要特殊处理 // 如果是binary类型的body需要特殊处理
if (param.getQueryParamsObj() != null && param.getQueryParamsObj().containsKey("binaryFile")) { if (param.getBinaryParamsObj() != null) {
apiDefinitionMockConfig = mockConfigs.stream() if (apiDefinitionMockConfig != null && !matchBinaryBody(apiDefinitionMockConfig, param.getBinaryParamsObj(), apiDefinitionMockList.getFirst().getProjectId())) {
.filter(mockConfig -> matchBinaryBody(mockConfig, param.getQueryParamsObj().get("binaryFile"), apiDefinitionMockList.getFirst().getProjectId())) apiDefinitionMockConfig = null;
.findFirst() }
.orElse(null);
} }
if (apiDefinitionMockConfig != null) { if (apiDefinitionMockConfig != null) {
ApiMockConfigDTO apiMockConfigDTO = new ApiMockConfigDTO(); ApiMockConfigDTO apiMockConfigDTO = new ApiMockConfigDTO();
@ -152,8 +147,9 @@ public class MockServerService {
return null; return null;
} }
private boolean matchBinaryBody(ApiDefinitionMockConfig mockConfig, String binaryFile, String projectId) { private boolean matchBinaryBody(ApiDefinitionMockConfig mockConfig, byte[] binaryFile, String projectId) {
BodyParamMatchRule bodyParamMatchRule = JSON.parseObject(new String(mockConfig.getMatching()), BodyParamMatchRule.class); MockMatchRule matchRule = JSON.parseObject(new String(mockConfig.getMatching()), MockMatchRule.class);
BodyParamMatchRule bodyParamMatchRule = matchRule.getBody();
if (bodyParamMatchRule != null && StringUtils.equals(bodyParamMatchRule.getBodyType(), Body.BodyType.BINARY.name())) { if (bodyParamMatchRule != null && StringUtils.equals(bodyParamMatchRule.getBodyType(), Body.BodyType.BINARY.name())) {
BinaryBody binaryBody = bodyParamMatchRule.getBinaryBody(); BinaryBody binaryBody = bodyParamMatchRule.getBinaryBody();
if (binaryBody != null && binaryBody.getFile() != null) { if (binaryBody != null && binaryBody.getFile() != null) {
@ -172,14 +168,14 @@ public class MockServerService {
FileRepository defaultRepository = FileCenter.getDefaultRepository(); FileRepository defaultRepository = FileCenter.getDefaultRepository();
FileRequest fileRequest = new FileRequest(); FileRequest fileRequest = new FileRequest();
fileRequest.setFileName(apiFileResource.getFileName()); fileRequest.setFileName(apiFileResource.getFileName());
fileRequest.setFolder(DefaultRepositoryDir.getApiDefinitionDir(projectId, mockConfig.getId()) + "/" + file.getFileId()); fileRequest.setFolder(DefaultRepositoryDir.getApiMockDir(projectId, mockConfig.getId()) + "/" + file.getFileId());
try { try {
bytes = defaultRepository.getFile(fileRequest); bytes = defaultRepository.getFile(fileRequest);
} catch (Exception ignore) { } catch (Exception ignore) {
} }
} }
} }
return StringUtils.equals(binaryFile, new String(bytes)); return StringUtils.equals(new String(binaryFile), new String(bytes));
} }
} }
return false; return false;
@ -236,19 +232,20 @@ public class MockServerService {
} }
if (responseBody != null) { if (responseBody != null) {
boolean isMock = config != null;
String resourceId = config != null ? config.getId() : apiId; String resourceId = config != null ? config.getId() : apiId;
return switch (responseBody.getBodyType()) { return switch (responseBody.getBodyType()) {
case "JSON" -> responseEntity(responseCode, responseBody.getJsonBody().getJsonWithSchema(), headers); case "JSON" -> responseEntity(responseCode, responseBody.getJsonBody().getJsonWithSchema(), headers);
case "XML" -> responseEntity(responseCode, responseBody.getXmlBody().getValue(), headers); case "XML" -> responseEntity(responseCode, responseBody.getXmlBody().getValue(), headers);
case "RAW" -> responseEntity(responseCode, responseBody.getRawBody().getValue(), headers); case "RAW" -> responseEntity(responseCode, responseBody.getRawBody().getValue(), headers);
default -> handleBinaryBody(responseBody, projectId, resourceId); default -> handleBinaryBody(responseBody, projectId, resourceId, isMock);
}; };
} }
return requestNotFound(); return requestNotFound();
} }
private ResponseEntity<?> handleBinaryBody(ResponseBody responseBody, String projectId, String resourceId) { private ResponseEntity<?> handleBinaryBody(ResponseBody responseBody, String projectId, String resourceId, boolean isMock) {
String fileId = responseBody.getBinaryBody().getFile().getFileId(); String fileId = responseBody.getBinaryBody().getFile().getFileId();
String fileName = responseBody.getBinaryBody().getFile().getFileName(); String fileName = responseBody.getBinaryBody().getFile().getFileName();
String fileType = StringUtils.substring(fileName, fileName.lastIndexOf(".") + 1); String fileType = StringUtils.substring(fileName, fileName.lastIndexOf(".") + 1);
@ -280,7 +277,8 @@ public class MockServerService {
FileRepository defaultRepository = FileCenter.getDefaultRepository(); FileRepository defaultRepository = FileCenter.getDefaultRepository();
FileRequest fileRequest = new FileRequest(); FileRequest fileRequest = new FileRequest();
fileRequest.setFileName(apiFileResource.getFileName()); fileRequest.setFileName(apiFileResource.getFileName());
fileRequest.setFolder(DefaultRepositoryDir.getApiDefinitionDir(projectId, resourceId) + "/" + fileId); String folder = isMock ? DefaultRepositoryDir.getApiMockDir(projectId, resourceId) : DefaultRepositoryDir.getApiDefinitionDir(projectId, resourceId);
fileRequest.setFolder(folder + "/" + fileId);
try { try {
bytes = defaultRepository.getFile(fileRequest); bytes = defaultRepository.getFile(fileRequest);
} catch (Exception ignore) { } catch (Exception ignore) {

View File

@ -42,11 +42,24 @@ public class MockServerUtils {
//解析k-v参数 //解析k-v参数
LinkedHashMap<String, String> queryParamsMap = new LinkedHashMap<>(); LinkedHashMap<String, String> queryParamsMap = new LinkedHashMap<>();
String requestPostString = null;
try { try {
if (request instanceof ShiroHttpServletRequest shiroHttpServletRequest) { if (request instanceof ShiroHttpServletRequest shiroHttpServletRequest) {
InputStream inputStream = shiroHttpServletRequest.getRequest().getInputStream(); InputStream inputStream = shiroHttpServletRequest.getRequest().getInputStream();
if (inputStream != null && inputStream.available() > 0) { if (inputStream != null && inputStream.available() > 0 && StringUtils.equals(request.getContentType(), MediaType.APPLICATION_OCTET_STREAM_VALUE)) {
queryParamsMap.put("binaryFile", new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)).readLine()); byte[] binaryParams = inputStream.readAllBytes();
requestParam.setBinaryParamsObj(binaryParams);
} else if (StringUtils.equals(request.getContentType(), MediaType.APPLICATION_JSON_VALUE)) {
String inputLine;
StringBuilder receiveData = new StringBuilder();
try (BufferedReader in = new BufferedReader(new InputStreamReader(
request.getInputStream(), StandardCharsets.UTF_8))) {
while ((inputLine = in.readLine()) != null) {
receiveData.append(inputLine);
}
}
requestPostString = receiveData.toString();
} }
} }
String queryString = request.getQueryString(); String queryString = request.getQueryString();
@ -75,12 +88,12 @@ public class MockServerUtils {
bodyParams.computeIfPresent(name, (key, currentValue) -> { bodyParams.computeIfPresent(name, (key, currentValue) -> {
List<String> current = JSON.parseArray(currentValue, String.class); List<String> current = JSON.parseArray(currentValue, String.class);
current.add(fileName); current.add(fileName);
return JSON.toJSONString(current); return current.toString();
}); });
if (!bodyParams.containsKey(name)) { if (!bodyParams.containsKey(name)) {
List<String> current = new ArrayList<>(); List<String> current = new ArrayList<>();
current.add(fileName); current.add(fileName);
bodyParams.put(name, JSON.toJSONString(current)); bodyParams.put(name, current.toString());
} }
} }
requestParam.setBodyParamsObj(bodyParams); requestParam.setBodyParamsObj(bodyParams);
@ -91,7 +104,6 @@ public class MockServerUtils {
} }
//解析body参数 //解析body参数
String requestPostString = getRequestStr(request);
requestParam.setRaw(requestPostString); requestParam.setRaw(requestPostString);
//解析paramType //解析paramType