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

View File

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

View File

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

View File

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

View File

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