refactor(接口测试): 优化mock执行匹配
This commit is contained in:
parent
23fddfc8dd
commit
a8af24681d
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 -> {
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue