refactor(接口测试): http请求详情设置请求方法等信息
This commit is contained in:
parent
6736cc5f17
commit
a6000793be
|
@ -281,7 +281,7 @@ public class ApiDefinitionController {
|
|||
@PostMapping("/debug")
|
||||
@Operation(summary = "接口调试")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_EXECUTE)
|
||||
public TaskRequestDTO debug(@Validated @RequestBody ApiRunRequest request) {
|
||||
public TaskRequestDTO debug(@Validated @RequestBody ApiDefinitionRunRequest request) {
|
||||
return apiDefinitionService.debug(request);
|
||||
}
|
||||
|
||||
|
|
|
@ -254,7 +254,7 @@ public class ApiTestCaseController {
|
|||
@PostMapping("/debug")
|
||||
@Operation(summary = "用例调试")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_CASE_EXECUTE)
|
||||
public TaskRequestDTO debug(@Validated @RequestBody ApiRunRequest request) {
|
||||
public TaskRequestDTO debug(@Validated @RequestBody ApiCaseRunRequest request) {
|
||||
return apiTestCaseService.debug(request);
|
||||
}
|
||||
|
||||
|
@ -270,7 +270,7 @@ public class ApiTestCaseController {
|
|||
@PostMapping("/run")
|
||||
@Operation(summary = "用例执行,传请求详情执行")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_CASE_EXECUTE)
|
||||
public TaskRequestDTO run(@Validated @RequestBody ApiRunRequest request) {
|
||||
public TaskRequestDTO run(@Validated @RequestBody ApiCaseRunRequest request) {
|
||||
return apiTestCaseService.run(request, SessionUtils.getUserId());
|
||||
}
|
||||
|
||||
|
|
|
@ -3,15 +3,24 @@ package io.metersphere.api.dto;
|
|||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 执行时需要设置的接口信息
|
||||
* @Author: jianxing
|
||||
* @CreateTime: 2024-02-17 18:46
|
||||
*/
|
||||
@Data
|
||||
public class ApiResourceModuleInfo {
|
||||
public class ApiDefinitionExecuteInfo {
|
||||
/**
|
||||
* 模块Id
|
||||
*/
|
||||
private String moduleId;
|
||||
/**
|
||||
* 请求方法
|
||||
*/
|
||||
private String method;
|
||||
/**
|
||||
* 请求路径
|
||||
*/
|
||||
private String path;
|
||||
/**
|
||||
* 资源id,接口定义,接口用例等
|
||||
*/
|
|
@ -0,0 +1,16 @@
|
|||
package io.metersphere.api.dto.definition;
|
||||
|
||||
import io.metersphere.api.dto.debug.ApiDebugRunRequest;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
@Data
|
||||
public class ApiCaseRunRequest extends ApiDebugRunRequest {
|
||||
@Schema(description = "环境ID")
|
||||
private String environmentId;
|
||||
@Schema(description = "接口定义ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank
|
||||
private String apiDefinitionId;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package io.metersphere.api.dto.definition;
|
||||
|
||||
import io.metersphere.api.dto.debug.ApiDebugRunRequest;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
@Data
|
||||
public class ApiDefinitionRunRequest extends ApiDebugRunRequest {
|
||||
@Schema(description = "环境ID")
|
||||
private String environmentId;
|
||||
|
||||
@Schema(description = "http协议类型post/get/其它协议则是协议名(mqtt)")
|
||||
@NotBlank
|
||||
private String method;
|
||||
|
||||
@Schema(description = "http协议路径/其它协议则为空")
|
||||
@NotBlank
|
||||
private String path;
|
||||
|
||||
@Schema(description = "模块fk")
|
||||
private String moduleId;
|
||||
}
|
|
@ -2,7 +2,7 @@ package io.metersphere.api.mapper;
|
|||
|
||||
import io.metersphere.api.domain.ApiDefinition;
|
||||
import io.metersphere.api.domain.ApiDefinitionCustomField;
|
||||
import io.metersphere.api.dto.ApiResourceModuleInfo;
|
||||
import io.metersphere.api.dto.ApiDefinitionExecuteInfo;
|
||||
import io.metersphere.api.dto.ReferenceDTO;
|
||||
import io.metersphere.api.dto.ReferenceRequest;
|
||||
import io.metersphere.api.dto.converter.ApiDefinitionImportDetail;
|
||||
|
@ -67,7 +67,7 @@ public interface ExtApiDefinitionMapper {
|
|||
|
||||
Long getLastPos(@Param("projectId") String projectId, @Param("basePos") Long basePos);
|
||||
|
||||
List<ApiResourceModuleInfo> getModuleInfoByIds(@Param("ids") List<String> ids);
|
||||
List<ApiDefinitionExecuteInfo> getApiDefinitionExecuteInfo(@Param("ids") List<String> ids);
|
||||
|
||||
ApiDefinition selectByProjectNumAndApiNum(@Param("projectNum") String projectNum, @Param("apiNum") String apiNum);
|
||||
|
||||
|
|
|
@ -547,10 +547,11 @@
|
|||
</if>
|
||||
order by `pos` desc limit 1;
|
||||
</select>
|
||||
<select id="getModuleInfoByIds" resultType="io.metersphere.api.dto.ApiResourceModuleInfo">
|
||||
select id as resource_id, module_id
|
||||
<select id="getApiDefinitionExecuteInfo" resultType="io.metersphere.api.dto.ApiDefinitionExecuteInfo">
|
||||
select id as resource_id, module_id, path, method
|
||||
from api_definition
|
||||
where id in
|
||||
where protocol = 'HTTP'
|
||||
and id in
|
||||
<foreach collection="ids" item="id" separator="," open="(" close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package io.metersphere.api.service;
|
||||
|
||||
import io.metersphere.api.domain.ApiDefinition;
|
||||
import io.metersphere.api.dto.ApiDefinitionExecuteInfo;
|
||||
import io.metersphere.api.dto.ApiFile;
|
||||
import io.metersphere.api.dto.definition.ResponseBinaryBody;
|
||||
import io.metersphere.api.dto.definition.ResponseBody;
|
||||
|
@ -21,6 +23,7 @@ import io.metersphere.project.dto.CommonScriptInfo;
|
|||
import io.metersphere.project.service.CustomFunctionService;
|
||||
import io.metersphere.project.service.FileAssociationService;
|
||||
import io.metersphere.project.service.FileMetadataService;
|
||||
import io.metersphere.sdk.util.BeanUtils;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
|
@ -266,4 +269,58 @@ public class ApiCommonService {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 MsHTTPElement 中的 method 等信息
|
||||
* @param httpElements
|
||||
* @param getDefinitionInfoFunc
|
||||
*/
|
||||
public void setApiDefinitionExecuteInfo(List<MsHTTPElement> httpElements, Function<List<String>, List<ApiDefinitionExecuteInfo>> getDefinitionInfoFunc) {
|
||||
if (CollectionUtils.isNotEmpty(httpElements)) {
|
||||
List<String> resourceIds = httpElements.stream().map(MsHTTPElement::getResourceId).collect(Collectors.toList());
|
||||
// 获取接口模块信息
|
||||
Map<String, ApiDefinitionExecuteInfo> resourceModuleMap = getApiDefinitionExecuteInfoMap(getDefinitionInfoFunc, resourceIds);
|
||||
httpElements.forEach(httpElement -> {
|
||||
ApiDefinitionExecuteInfo definitionExecuteInfo = resourceModuleMap.get(httpElement.getResourceId());
|
||||
// httpElement 设置模块,请求方法等信息
|
||||
setApiDefinitionExecuteInfo(httpElement, definitionExecuteInfo);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取资源 ID 和接口定义信息 的 Map
|
||||
* @param getDefinitionInfoFunc
|
||||
* @param resourceIds
|
||||
* @return
|
||||
*/
|
||||
public Map<String, ApiDefinitionExecuteInfo> getApiDefinitionExecuteInfoMap(Function<List<String>, List<ApiDefinitionExecuteInfo>> getDefinitionInfoFunc, List<String> resourceIds) {
|
||||
Map<String, ApiDefinitionExecuteInfo> resourceModuleMap = getDefinitionInfoFunc.apply(resourceIds)
|
||||
.stream()
|
||||
.collect(Collectors.toMap(ApiDefinitionExecuteInfo::getResourceId, Function.identity()));
|
||||
return resourceModuleMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 MsHTTPElement 中的 method 等信息
|
||||
* @param msTestElement
|
||||
* @param definitionExecuteInfo
|
||||
*/
|
||||
public void setApiDefinitionExecuteInfo(AbstractMsTestElement msTestElement, ApiDefinitionExecuteInfo definitionExecuteInfo) {
|
||||
if (msTestElement instanceof MsHTTPElement httpElement && definitionExecuteInfo != null) {
|
||||
httpElement.setModuleId(definitionExecuteInfo.getModuleId());
|
||||
httpElement.setMethod(definitionExecuteInfo.getMethod());
|
||||
httpElement.setPath(definitionExecuteInfo.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 给 httpElement 设置接口定义参数
|
||||
* @param apiDefinition
|
||||
* @param msTestElement
|
||||
*/
|
||||
public void setApiDefinitionExecuteInfo(AbstractMsTestElement msTestElement, ApiDefinition apiDefinition) {
|
||||
setApiDefinitionExecuteInfo(msTestElement, BeanUtils.copyBean(new ApiDefinitionExecuteInfo(), apiDefinition));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -257,10 +257,6 @@ public class ApiDefinitionService extends MoveNodeService {
|
|||
checkResponseNameCode(request.getResponse());
|
||||
if (originApiDefinition.getProtocol().equals(ModuleConstants.NODE_PROTOCOL_HTTP)) {
|
||||
checkUpdateExist(apiDefinition, originApiDefinition);
|
||||
//http协议的接口,如果修改了path和method,需要同步把case的path和method修改
|
||||
if (!originApiDefinition.getPath().equals(apiDefinition.getPath()) || !originApiDefinition.getMethod().equals(apiDefinition.getMethod())) {
|
||||
apiTestCaseService.updateByApiDefinitionId(List.of(request.getId()), apiDefinition);
|
||||
}
|
||||
}
|
||||
apiDefinition.setUpdateUser(userId);
|
||||
apiDefinition.setUpdateTime(System.currentTimeMillis());
|
||||
|
@ -880,6 +876,7 @@ public class ApiDefinitionService extends MoveNodeService {
|
|||
|
||||
public ApiDefinitionDTO getApiDefinitionInfo(String id, String userId, ApiDefinition apiDefinition) {
|
||||
ApiDefinitionDTO apiDefinitionDTO = new ApiDefinitionDTO();
|
||||
BeanUtils.copyBean(apiDefinitionDTO, apiDefinition);
|
||||
// 2. 使用Optional避免空指针异常
|
||||
handleBlob(id, apiDefinitionDTO);
|
||||
// 3. 查询自定义字段
|
||||
|
@ -888,7 +885,6 @@ public class ApiDefinitionService extends MoveNodeService {
|
|||
ApiDefinitionFollowerExample example = new ApiDefinitionFollowerExample();
|
||||
example.createCriteria().andApiDefinitionIdEqualTo(id).andUserIdEqualTo(userId);
|
||||
apiDefinitionDTO.setFollow(apiDefinitionFollowerMapper.countByExample(example) > 0);
|
||||
BeanUtils.copyBean(apiDefinitionDTO, apiDefinition);
|
||||
Set<String> userIds = extractUserIds(List.of(apiDefinitionDTO));
|
||||
Map<String, String> userMap = userLoginService.getUserNameMap(new ArrayList<>(userIds));
|
||||
apiDefinitionDTO.setCreateUserName(userMap.get(apiDefinitionDTO.getCreateUser()));
|
||||
|
@ -900,8 +896,11 @@ public class ApiDefinitionService extends MoveNodeService {
|
|||
Optional<ApiDefinitionBlob> apiDefinitionBlobOptional = Optional.ofNullable(apiDefinitionBlobMapper.selectByPrimaryKey(id));
|
||||
apiDefinitionBlobOptional.ifPresent(blob -> {
|
||||
AbstractMsTestElement msTestElement = ApiDataUtils.parseObject(new String(blob.getRequest()), AbstractMsTestElement.class);
|
||||
|
||||
apiCommonService.setLinkFileInfo(id, msTestElement);
|
||||
apiCommonService.setEnableCommonScriptProcessorInfo(msTestElement);
|
||||
apiCommonService.setApiDefinitionExecuteInfo(msTestElement, apiDefinitionDTO);
|
||||
|
||||
apiDefinitionDTO.setRequest(msTestElement);
|
||||
// blob.getResponse() 为 null 时不进行转换
|
||||
if (blob.getResponse() != null) {
|
||||
|
@ -1117,8 +1116,8 @@ public class ApiDefinitionService extends MoveNodeService {
|
|||
}
|
||||
}
|
||||
|
||||
public List<ApiResourceModuleInfo> getModuleInfoByIds(List<String> apiIds) {
|
||||
return extApiDefinitionMapper.getModuleInfoByIds(apiIds);
|
||||
public List<ApiDefinitionExecuteInfo> getModuleInfoByIds(List<String> apiIds) {
|
||||
return extApiDefinitionMapper.getApiDefinitionExecuteInfo(apiIds);
|
||||
}
|
||||
|
||||
public void checkModuleExist(String moduleId) {
|
||||
|
@ -1171,7 +1170,7 @@ public class ApiDefinitionService extends MoveNodeService {
|
|||
return apiFileResourceService.transfer(request, userId, ApiResourceType.API.name());
|
||||
}
|
||||
|
||||
public TaskRequestDTO debug(ApiRunRequest request) {
|
||||
public TaskRequestDTO debug(ApiDefinitionRunRequest request) {
|
||||
ApiResourceRunRequest runRequest = apiExecuteService.getApiResourceRunRequest(request);
|
||||
EnvironmentInfoDTO environmentInfoDTO = environmentService.get(request.getEnvironmentId());
|
||||
ApiParamConfig apiParamConfig = apiExecuteService.getApiParamConfig(request.getReportId());
|
||||
|
@ -1182,8 +1181,13 @@ public class ApiDefinitionService extends MoveNodeService {
|
|||
taskRequest.setResourceType(ApiResourceType.API.name());
|
||||
taskRequest.setRunMode(apiExecuteService.getDebugRunModule(request.getFrontendDebug()));
|
||||
|
||||
AbstractMsTestElement msTestElement = runRequest.getTestElement();
|
||||
|
||||
// 设置 method 等信息
|
||||
apiCommonService.setApiDefinitionExecuteInfo(msTestElement, BeanUtils.copyBean(new ApiDefinition(), request));
|
||||
// 设置环境
|
||||
apiParamConfig.setEnvConfig(environmentInfoDTO);
|
||||
|
||||
return apiExecuteService.apiExecute(runRequest, taskRequest, apiParamConfig);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
package io.metersphere.api.service.definition;
|
||||
|
||||
import io.metersphere.api.domain.*;
|
||||
import io.metersphere.api.dto.ApiDefinitionExecuteInfo;
|
||||
import io.metersphere.api.dto.ApiParamConfig;
|
||||
import io.metersphere.api.dto.debug.ApiResourceRunRequest;
|
||||
import io.metersphere.api.dto.definition.ApiTestCaseBatchRunRequest;
|
||||
import io.metersphere.api.mapper.ApiDefinitionMapper;
|
||||
import io.metersphere.api.mapper.ApiTestCaseBlobMapper;
|
||||
import io.metersphere.api.mapper.ApiTestCaseMapper;
|
||||
import io.metersphere.api.mapper.ExtApiTestCaseMapper;
|
||||
import io.metersphere.api.service.ApiBatchRunBaseService;
|
||||
import io.metersphere.api.service.ApiCommonService;
|
||||
import io.metersphere.api.service.ApiExecuteService;
|
||||
import io.metersphere.api.service.queue.ApiExecutionQueueService;
|
||||
import io.metersphere.api.service.queue.ApiExecutionSetService;
|
||||
|
@ -63,6 +66,10 @@ public class ApiTestCaseBatchRunService {
|
|||
private ApiReportService apiReportService;
|
||||
@Resource
|
||||
private ApiBatchRunBaseService apiBatchRunBaseService;
|
||||
@Resource
|
||||
private ApiCommonService apiCommonService;
|
||||
@Resource
|
||||
private ApiDefinitionMapper apiDefinitionMapper;
|
||||
|
||||
/**
|
||||
* 异步批量执行
|
||||
|
@ -132,6 +139,8 @@ public class ApiTestCaseBatchRunService {
|
|||
// 分批处理
|
||||
SubListUtils.dealForSubList(ids, 100, subIds -> {
|
||||
List<ApiTestCase> apiTestCases = extApiTestCaseMapper.getApiCaseExecuteInfoByIds(subIds);
|
||||
// 获取用例和定义信息的map,key 为用例ID,value 为接口定义信息
|
||||
Map<String, ApiDefinitionExecuteInfo> definitionExecuteInfoMap = apiCommonService.getApiDefinitionExecuteInfoMap(apiTestCaseService::getModuleInfoByIds, subIds);
|
||||
|
||||
Map<String, String> caseReportMap = null;
|
||||
String integratedReportId = null;
|
||||
|
@ -174,7 +183,7 @@ public class ApiTestCaseBatchRunService {
|
|||
// 如果是集成报告则生成唯一的虚拟ID,非集成报告使用单用例的报告ID
|
||||
reportId = runModeConfig.isIntegratedReport() ? UUID.randomUUID().toString() : caseReportMap.get(id);
|
||||
TaskRequestDTO taskRequest = getTaskRequestDTO(reportId, apiTestCase, runModeConfig);
|
||||
execute(taskRequest, apiTestCase, apiTestCaseBlob);
|
||||
execute(taskRequest, apiTestCase, apiTestCaseBlob, definitionExecuteInfoMap.get(apiTestCase.getId()));
|
||||
} catch (Exception e) {
|
||||
LogUtils.error("执行用例失败 {}-{}", reportId, id);
|
||||
LogUtils.error(e);
|
||||
|
@ -270,6 +279,7 @@ public class ApiTestCaseBatchRunService {
|
|||
LogUtils.info("当前执行任务的用例已删除 {}", resourceId);
|
||||
return;
|
||||
}
|
||||
ApiDefinition apiDefinition = apiDefinitionMapper.selectByPrimaryKey(apiTestCase.getApiDefinitionId());
|
||||
|
||||
String reportId;
|
||||
if (runModeConfig.isIntegratedReport()) {
|
||||
|
@ -281,7 +291,7 @@ public class ApiTestCaseBatchRunService {
|
|||
}
|
||||
TaskRequestDTO taskRequest = getTaskRequestDTO(reportId, apiTestCase, runModeConfig);
|
||||
taskRequest.setQueueId(queue.getQueueId());
|
||||
execute(taskRequest, apiTestCase, apiTestCaseBlob);
|
||||
execute(taskRequest, apiTestCase, apiTestCaseBlob, BeanUtils.copyBean(new ApiDefinitionExecuteInfo(), apiDefinition));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -290,12 +300,16 @@ public class ApiTestCaseBatchRunService {
|
|||
* @param apiTestCase
|
||||
* @param apiTestCaseBlob
|
||||
*/
|
||||
public void execute(TaskRequestDTO taskRequest, ApiTestCase apiTestCase, ApiTestCaseBlob apiTestCaseBlob) {
|
||||
public void execute(TaskRequestDTO taskRequest, ApiTestCase apiTestCase, ApiTestCaseBlob apiTestCaseBlob, ApiDefinitionExecuteInfo definitionExecuteInfo) {
|
||||
ApiParamConfig apiParamConfig = apiExecuteService.getApiParamConfig(taskRequest.getReportId());
|
||||
apiParamConfig.setEnvConfig(environmentService.get(getEnvId(taskRequest.getRunModeConfig(), apiTestCase)));
|
||||
|
||||
ApiResourceRunRequest runRequest = new ApiResourceRunRequest();
|
||||
runRequest.setTestElement(ApiDataUtils.parseObject(new String(apiTestCaseBlob.getRequest()), AbstractMsTestElement.class));
|
||||
|
||||
// 设置环境信息
|
||||
apiParamConfig.setEnvConfig(environmentService.get(getEnvId(taskRequest.getRunModeConfig(), apiTestCase)));
|
||||
// 设置 method 等信息
|
||||
apiCommonService.setApiDefinitionExecuteInfo(runRequest.getTestElement(), definitionExecuteInfo);
|
||||
|
||||
apiExecuteService.apiExecute(runRequest, taskRequest, apiParamConfig);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ import io.metersphere.api.dto.debug.ApiFileResourceUpdateRequest;
|
|||
import io.metersphere.api.dto.debug.ApiResourceRunRequest;
|
||||
import io.metersphere.api.dto.definition.*;
|
||||
import io.metersphere.api.dto.request.ApiTransferRequest;
|
||||
import io.metersphere.api.dto.request.http.MsHTTPElement;
|
||||
import io.metersphere.api.mapper.*;
|
||||
import io.metersphere.api.service.ApiCommonService;
|
||||
import io.metersphere.api.service.ApiExecuteService;
|
||||
|
@ -224,6 +223,7 @@ public class ApiTestCaseService extends MoveNodeService {
|
|||
AbstractMsTestElement msTestElement = ApiDataUtils.parseObject(new String(testCaseBlob.getRequest()), AbstractMsTestElement.class);
|
||||
apiCommonService.setLinkFileInfo(id, msTestElement);
|
||||
apiCommonService.setEnableCommonScriptProcessorInfo(msTestElement);
|
||||
apiCommonService.setApiDefinitionExecuteInfo(msTestElement, apiDefinition);
|
||||
apiTestCaseDTO.setRequest(msTestElement);
|
||||
return apiTestCaseDTO;
|
||||
}
|
||||
|
@ -518,37 +518,6 @@ public class ApiTestCaseService extends MoveNodeService {
|
|||
return apiFileResourceService.uploadTempFile(file);
|
||||
}
|
||||
|
||||
public void updateByApiDefinitionId(List<String> ids, ApiDefinition apiDefinition) {
|
||||
String method = apiDefinition.getMethod();
|
||||
String path = apiDefinition.getPath();
|
||||
if (StringUtils.isNotEmpty(method) || StringUtils.isNotEmpty(path)) {
|
||||
ApiTestCaseExample apiTestCaseExample = new ApiTestCaseExample();
|
||||
apiTestCaseExample.createCriteria().andApiDefinitionIdIn(ids);
|
||||
List<ApiTestCase> caseLists = apiTestCaseMapper.selectByExample(apiTestCaseExample);
|
||||
List<String> caseIds = caseLists.stream().map(ApiTestCase::getId).toList();
|
||||
if (CollectionUtils.isEmpty(caseIds)) {
|
||||
return;
|
||||
}
|
||||
ApiTestCaseBlobExample blobExample = new ApiTestCaseBlobExample();
|
||||
blobExample.createCriteria().andIdIn(caseIds);
|
||||
List<ApiTestCaseBlob> bloBs = apiTestCaseBlobMapper.selectByExampleWithBLOBs(blobExample);
|
||||
|
||||
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
||||
ApiTestCaseBlobMapper batchMapper = sqlSession.getMapper(ApiTestCaseBlobMapper.class);
|
||||
bloBs.forEach(apiTestCase -> {
|
||||
MsHTTPElement msHttpElement = ApiDataUtils.parseObject(new String(apiTestCase.getRequest()), MsHTTPElement.class);
|
||||
msHttpElement.setMethod(method);
|
||||
msHttpElement.setPath(path);
|
||||
apiTestCase.setRequest(ApiDataUtils.toJSONString(msHttpElement).getBytes());
|
||||
batchMapper.updateByPrimaryKeySelective(apiTestCase);
|
||||
});
|
||||
sqlSession.flushStatements();
|
||||
if (sqlSessionFactory != null) {
|
||||
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<ApiTestCaseBlob> getBlobByIds(List<String> apiCaseIds) {
|
||||
if (CollectionUtils.isEmpty(apiCaseIds)) {
|
||||
return Collections.emptyList();
|
||||
|
@ -590,7 +559,7 @@ public class ApiTestCaseService extends MoveNodeService {
|
|||
apiTestCaseMapper.updateByPrimaryKeySelective(update);
|
||||
}
|
||||
|
||||
public List<ApiResourceModuleInfo> getModuleInfoByIds(List<String> ids) {
|
||||
public List<ApiDefinitionExecuteInfo> getModuleInfoByIds(List<String> ids) {
|
||||
// 获取接口定义ID和用例ID的映射
|
||||
Map<String, String> apiCaseDefinitionMap = extApiTestCaseMapper.getApiCaseDefinitionInfo(ids)
|
||||
.stream()
|
||||
|
@ -600,11 +569,11 @@ public class ApiTestCaseService extends MoveNodeService {
|
|||
if (CollectionUtils.isEmpty(definitionIds)) {
|
||||
return List.of();
|
||||
}
|
||||
List<ApiResourceModuleInfo> moduleInfos = extApiDefinitionMapper.getModuleInfoByIds(definitionIds);
|
||||
List<ApiDefinitionExecuteInfo> definitionExecuteInfos = extApiDefinitionMapper.getApiDefinitionExecuteInfo(definitionIds);
|
||||
// 将 resourceId 从定义ID替换成用例ID
|
||||
moduleInfos.forEach(moduleInfo ->
|
||||
moduleInfo.setResourceId(apiCaseDefinitionMap.get(moduleInfo.getResourceId())));
|
||||
return moduleInfos;
|
||||
definitionExecuteInfos.forEach(info ->
|
||||
info.setResourceId(apiCaseDefinitionMap.get(info.getResourceId())));
|
||||
return definitionExecuteInfos;
|
||||
}
|
||||
|
||||
public void handleFileAssociationUpgrade(FileAssociation originFileAssociation, FileMetadata newFileMetadata) {
|
||||
|
@ -636,7 +605,7 @@ public class ApiTestCaseService extends MoveNodeService {
|
|||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public TaskRequestDTO run(ApiRunRequest request, String userId) {
|
||||
public TaskRequestDTO run(ApiCaseRunRequest request, String userId) {
|
||||
ApiTestCase apiTestCase = checkResourceExist(request.getId());
|
||||
ApiResourceRunRequest runRequest = apiExecuteService.getApiResourceRunRequest(request);
|
||||
apiTestCase.setEnvironmentId(request.getEnvironmentId());
|
||||
|
@ -689,7 +658,7 @@ public class ApiTestCaseService extends MoveNodeService {
|
|||
// 初始化报告
|
||||
initApiReport(apiTestCase, reportId, poolId, userId);
|
||||
|
||||
return doExecute(taskRequest, runRequest, apiTestCase.getEnvironmentId());
|
||||
return doExecute(taskRequest, runRequest, apiTestCase.getApiDefinitionId(), apiTestCase.getEnvironmentId());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -698,7 +667,7 @@ public class ApiTestCaseService extends MoveNodeService {
|
|||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public TaskRequestDTO debug(ApiRunRequest request) {
|
||||
public TaskRequestDTO debug(ApiCaseRunRequest request) {
|
||||
TaskRequestDTO taskRequest = getTaskRequest(request.getReportId(), request.getId(),
|
||||
request.getProjectId(), apiExecuteService.getDebugRunModule(request.getFrontendDebug()));
|
||||
taskRequest.setSaveResult(false);
|
||||
|
@ -706,14 +675,19 @@ public class ApiTestCaseService extends MoveNodeService {
|
|||
|
||||
ApiResourceRunRequest runRequest = apiExecuteService.getApiResourceRunRequest(request);
|
||||
|
||||
return doExecute(taskRequest, runRequest, request.getEnvironmentId());
|
||||
return doExecute(taskRequest, runRequest, request.getApiDefinitionId(), request.getEnvironmentId());
|
||||
}
|
||||
|
||||
private TaskRequestDTO doExecute(TaskRequestDTO taskRequest, ApiResourceRunRequest runRequest, String envId) {
|
||||
private TaskRequestDTO doExecute(TaskRequestDTO taskRequest, ApiResourceRunRequest runRequest, String apiDefinitionId, String envId) {
|
||||
|
||||
ApiParamConfig apiParamConfig = apiExecuteService.getApiParamConfig(taskRequest.getReportId());
|
||||
|
||||
ApiDefinition apiDefinition = apiDefinitionMapper.selectByPrimaryKey(apiDefinitionId);
|
||||
|
||||
// 设置环境
|
||||
apiParamConfig.setEnvConfig(environmentService.get(envId));
|
||||
// 设置 method 等信息
|
||||
apiCommonService.setApiDefinitionExecuteInfo(runRequest.getTestElement(), apiDefinition);
|
||||
|
||||
return apiExecuteService.apiExecute(runRequest, taskRequest, apiParamConfig);
|
||||
}
|
||||
|
|
|
@ -29,17 +29,13 @@ import io.metersphere.sdk.util.BeanUtils;
|
|||
import io.metersphere.sdk.util.LogUtils;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
|
|
|
@ -1110,6 +1110,7 @@ public class ApiScenarioService extends MoveNodeService {
|
|||
ApiScenarioParseParam parseParam,
|
||||
String reportId, String userId) {
|
||||
|
||||
// 解析生成场景树,并保存临时变量
|
||||
ApiScenarioParseTmpParam tmpParam = parse(msScenario, steps, parseParam);
|
||||
|
||||
ApiResourceRunRequest runRequest = getApiResourceRunRequest(msScenario, tmpParam);
|
||||
|
@ -1283,7 +1284,7 @@ public class ApiScenarioService extends MoveNodeService {
|
|||
parseStep2MsElement(msScenario, steps, tmpParam);
|
||||
|
||||
// 设置 HttpElement 的模块信息
|
||||
setHttpElementModuleId(tmpParam.getStepTypeHttpElementMap());
|
||||
setApiDefinitionExecuteInfo(tmpParam.getStepTypeHttpElementMap());
|
||||
|
||||
// 设置使用脚本前后置的公共脚本信息
|
||||
apiCommonService.setEnableCommonScriptProcessorInfo(tmpParam.getCommonElements());
|
||||
|
@ -1304,23 +1305,9 @@ public class ApiScenarioService extends MoveNodeService {
|
|||
*
|
||||
* @param stepTypeHttpElementMap
|
||||
*/
|
||||
private void setHttpElementModuleId(Map<String, List<MsHTTPElement>> stepTypeHttpElementMap) {
|
||||
setHttpElementModuleId(stepTypeHttpElementMap.get(ApiScenarioStepType.API.name()), apiDefinitionService::getModuleInfoByIds);
|
||||
setHttpElementModuleId(stepTypeHttpElementMap.get(ApiScenarioStepType.API_CASE.name()), apiTestCaseService::getModuleInfoByIds);
|
||||
}
|
||||
|
||||
private void setHttpElementModuleId(List<MsHTTPElement> httpElements, Function<List<String>, List<ApiResourceModuleInfo>> getModuleInfoFunc) {
|
||||
if (CollectionUtils.isNotEmpty(httpElements)) {
|
||||
List<String> apiIds = httpElements.stream().map(MsHTTPElement::getResourceId).collect(Collectors.toList());
|
||||
// 获取接口模块信息
|
||||
Map<String, String> resourceModuleMap = getModuleInfoFunc.apply(apiIds)
|
||||
.stream()
|
||||
.collect(Collectors.toMap(ApiResourceModuleInfo::getResourceId, ApiResourceModuleInfo::getModuleId));
|
||||
httpElements.forEach(httpElement -> {
|
||||
// httpElement 设置模块信息
|
||||
httpElement.setModuleId(resourceModuleMap.get(httpElement.getResourceId()));
|
||||
});
|
||||
}
|
||||
private void setApiDefinitionExecuteInfo(Map<String, List<MsHTTPElement>> stepTypeHttpElementMap) {
|
||||
apiCommonService.setApiDefinitionExecuteInfo(stepTypeHttpElementMap.get(ApiScenarioStepType.API.name()), apiDefinitionService::getModuleInfoByIds);
|
||||
apiCommonService.setApiDefinitionExecuteInfo(stepTypeHttpElementMap.get(ApiScenarioStepType.API_CASE.name()), apiTestCaseService::getModuleInfoByIds);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1615,7 +1602,7 @@ public class ApiScenarioService extends MoveNodeService {
|
|||
*/
|
||||
private boolean hasStepDetail(String stepType) {
|
||||
return !StringUtils.equals(stepType, ApiScenarioStepRefType.REF.name())
|
||||
|| StringUtils.equals(stepType, ApiScenarioStepType.API.name());
|
||||
|| isApi(stepType);
|
||||
}
|
||||
|
||||
private Map<String, String> getResourceDetailMap(Map<String, List<String>> refResourceMap) {
|
||||
|
@ -1772,7 +1759,15 @@ public class ApiScenarioService extends MoveNodeService {
|
|||
* 引用的接口定义允许修改参数值,需要特殊处理
|
||||
*/
|
||||
private boolean isRefApi(String stepType, String refType) {
|
||||
return StringUtils.equals(stepType, ApiScenarioStepType.API.name()) && StringUtils.equals(refType, ApiScenarioStepRefType.REF.name());
|
||||
return isApi(stepType) && StringUtils.equals(refType, ApiScenarioStepRefType.REF.name());
|
||||
}
|
||||
|
||||
private boolean isApi(String stepType) {
|
||||
return StringUtils.equals(stepType, ApiScenarioStepType.API.name());
|
||||
}
|
||||
|
||||
private boolean isApiCase(String stepType) {
|
||||
return StringUtils.equals(stepType, ApiScenarioStepType.API_CASE.name());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1865,6 +1860,14 @@ public class ApiScenarioService extends MoveNodeService {
|
|||
// 设置关联的文件的最新信息
|
||||
if (isRef(step.getRefType())) {
|
||||
apiCommonService.setLinkFileInfo(step.getResourceId(), msTestElement);
|
||||
if (isApi(step.getStepType())) {
|
||||
ApiDefinition apiDefinition = apiDefinitionMapper.selectByPrimaryKey(step.getResourceId());
|
||||
apiCommonService.setApiDefinitionExecuteInfo(msTestElement, apiDefinition);
|
||||
} else if (isApiCase(step.getStepType())) {
|
||||
ApiTestCase apiTestCase = apiTestCaseMapper.selectByPrimaryKey(step.getResourceId());
|
||||
ApiDefinition apiDefinition = apiDefinitionMapper.selectByPrimaryKey(apiTestCase.getApiDefinitionId());
|
||||
apiCommonService.setApiDefinitionExecuteInfo(msTestElement, apiDefinition);
|
||||
}
|
||||
} else {
|
||||
apiCommonService.setLinkFileInfo(step.getScenarioId(), msTestElement);
|
||||
}
|
||||
|
|
|
@ -414,6 +414,10 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
if (apiDefinitionBlob != null) {
|
||||
AbstractMsTestElement msTestElement = ApiDataUtils.parseObject(new String(apiDefinitionBlob.getRequest()), AbstractMsTestElement.class);
|
||||
apiCommonService.setLinkFileInfo(apiDefinition.getId(), msTestElement);
|
||||
MsHTTPElement msHTTPElement = (MsHTTPElement) msTestElement;
|
||||
msHTTPElement.setMethod(apiDefinition.getMethod());
|
||||
msHTTPElement.setPath(apiDefinition.getPath());
|
||||
msHTTPElement.setModuleId(apiDefinition.getModuleId());
|
||||
copyApiDefinitionDTO.setRequest(msTestElement);
|
||||
List<HttpResponse> httpResponses = ApiDataUtils.parseArray(new String(apiDefinitionBlob.getResponse()), HttpResponse.class);
|
||||
for (HttpResponse httpResponse : httpResponses) {
|
||||
|
@ -421,6 +425,11 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
}
|
||||
copyApiDefinitionDTO.setResponse(httpResponses);
|
||||
}
|
||||
|
||||
MsHTTPElement msHTTPElement = (MsHTTPElement) apiDefinitionDTO.getRequest();
|
||||
Assertions.assertEquals(msHTTPElement.getMethod(), apiDefinition.getMethod());
|
||||
Assertions.assertEquals(msHTTPElement.getPath(), apiDefinition.getPath());
|
||||
Assertions.assertEquals(msHTTPElement.getModuleId(), apiDefinition.getModuleId());
|
||||
Assertions.assertEquals(apiDefinitionDTO, copyApiDefinitionDTO);
|
||||
|
||||
assertErrorCode(this.requestGet(GET + "111"), ApiResultCode.API_DEFINITION_NOT_EXIST);
|
||||
|
@ -568,19 +577,7 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
}
|
||||
updateRequest.setPath("/api/test/path/method/case");
|
||||
this.requestPostWithOk(UPDATE, updateRequest);
|
||||
//校验用例是否被修改
|
||||
ApiTestCaseExample apiTestCaseExample = new ApiTestCaseExample();
|
||||
apiTestCaseExample.createCriteria().andApiDefinitionIdEqualTo(apiPathAndMethod.getId());
|
||||
List<ApiTestCase> apiTestCases = apiTestCaseMapper.selectByExample(apiTestCaseExample);
|
||||
List<String> caseIds = apiTestCases.stream().map(ApiTestCase::getId).toList();
|
||||
ApiTestCaseBlobExample apiTestCaseBlobExample = new ApiTestCaseBlobExample();
|
||||
apiTestCaseBlobExample.createCriteria().andIdIn(caseIds);
|
||||
List<ApiTestCaseBlob> apiTestCaseBlobs = apiTestCaseBlobMapper.selectByExampleWithBLOBs(apiTestCaseBlobExample);
|
||||
apiTestCaseBlobs.forEach(apiTestCaseBlob -> {
|
||||
MsHTTPElement caseElement = ApiDataUtils.parseObject(new String(apiTestCaseBlob.getRequest()), MsHTTPElement.class);
|
||||
Assertions.assertEquals(updateRequest.getPath(), caseElement.getPath());
|
||||
Assertions.assertEquals(updateRequest.getMethod(), caseElement.getMethod());
|
||||
});
|
||||
|
||||
// @@校验权限
|
||||
request.setId(apiDefinition.getId());
|
||||
request.setName("permission-st-6");
|
||||
|
@ -591,7 +588,7 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
@Test
|
||||
@Order(4)
|
||||
public void debug() throws Exception {
|
||||
ApiRunRequest request = new ApiRunRequest();
|
||||
ApiDefinitionRunRequest request = new ApiDefinitionRunRequest();
|
||||
request.setId(apiDefinition.getId());
|
||||
MsHTTPElement msHTTPElement = new MsHTTPElement();
|
||||
msHTTPElement.setPath("/test");
|
||||
|
@ -599,6 +596,8 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
request.setRequest(JSON.parseObject(ApiDataUtils.toJSONString(msHTTPElement)));
|
||||
request.setReportId(IDGenerator.nextStr());
|
||||
request.setProjectId(DEFAULT_PROJECT_ID);
|
||||
request.setPath("/test");
|
||||
request.setMethod("GET");
|
||||
MvcResult mvcResult = this.requestPostAndReturn(DEBUG, request);
|
||||
ResultHolder resultHolder = JSON.parseObject(mvcResult.getResponse().getContentAsString(Charset.defaultCharset()), ResultHolder.class);
|
||||
Assertions.assertTrue(resultHolder.getCode() == ApiResultCode.RESOURCE_POOL_EXECUTE_ERROR.getCode() ||
|
||||
|
|
|
@ -420,7 +420,7 @@ public class ApiTestCaseControllerTests extends BaseTest {
|
|||
@Test
|
||||
@Order(3)
|
||||
public void debug() throws Exception {
|
||||
ApiRunRequest request = new ApiRunRequest();
|
||||
ApiCaseRunRequest request = new ApiCaseRunRequest();
|
||||
request.setId(apiTestCase.getId());
|
||||
MsHTTPElement msHTTPElement = new MsHTTPElement();
|
||||
msHTTPElement.setPath("/test");
|
||||
|
@ -428,6 +428,7 @@ public class ApiTestCaseControllerTests extends BaseTest {
|
|||
request.setRequest(JSON.parseObject(ApiDataUtils.toJSONString(msHTTPElement)));
|
||||
request.setReportId(IDGenerator.nextStr());
|
||||
request.setProjectId(DEFAULT_PROJECT_ID);
|
||||
request.setApiDefinitionId(apiTestCase.getApiDefinitionId());
|
||||
MvcResult mvcResult = this.requestPostAndReturn(DEBUG, request);
|
||||
ResultHolder resultHolder = JSON.parseObject(mvcResult.getResponse().getContentAsString(Charset.defaultCharset()), ResultHolder.class);
|
||||
Assertions.assertTrue(resultHolder.getCode() == ApiResultCode.RESOURCE_POOL_EXECUTE_ERROR.getCode() ||
|
||||
|
@ -548,8 +549,18 @@ public class ApiTestCaseControllerTests extends BaseTest {
|
|||
copyApiDebugDTO.setFollow(CollectionUtils.isNotEmpty(followers));
|
||||
AbstractMsTestElement msTestElement = ApiDataUtils.parseObject(new String(apiTestCaseBlob.getRequest()), AbstractMsTestElement.class);
|
||||
apiCommonService.setLinkFileInfo(apiTestCase.getId(), msTestElement);
|
||||
MsHTTPElement msHTTPElement = (MsHTTPElement) msTestElement;
|
||||
msHTTPElement.setMethod(apiDefinition.getMethod());
|
||||
msHTTPElement.setPath(apiDefinition.getPath());
|
||||
msHTTPElement.setModuleId(apiDefinition.getModuleId());
|
||||
copyApiDebugDTO.setRequest(msTestElement);
|
||||
|
||||
msHTTPElement = (MsHTTPElement) apiDebugDTO.getRequest();
|
||||
Assertions.assertEquals(msHTTPElement.getMethod(), apiDefinition.getMethod());
|
||||
Assertions.assertEquals(msHTTPElement.getPath(), apiDefinition.getPath());
|
||||
Assertions.assertEquals(msHTTPElement.getModuleId(), apiDefinition.getModuleId());
|
||||
Assertions.assertEquals(apiDebugDTO, copyApiDebugDTO);
|
||||
|
||||
this.requestGetWithOk(GET + anotherApiTestCase.getId())
|
||||
.andReturn();
|
||||
|
||||
|
|
|
@ -380,6 +380,7 @@ export interface ExecuteRequestParams {
|
|||
request: ExecuteApiRequestFullParams | ExecutePluginRequestParams;
|
||||
projectId: string;
|
||||
frontendDebug?: boolean; // 是否本地调试,该模式下接口会返回执行参数,用来调用本地执行服务
|
||||
apiDefinitionId?: string | number; // 接口用例执行和调试时需要传
|
||||
}
|
||||
// 响应结果
|
||||
export interface ResponseResult {
|
||||
|
|
|
@ -345,7 +345,6 @@ export interface AddApiCaseParams extends ExecuteRequestParams {
|
|||
name: string;
|
||||
priority: string;
|
||||
status: string;
|
||||
apiDefinitionId?: string | number;
|
||||
tags: string[];
|
||||
deleteFileIds?: string[];
|
||||
unLinkFileIds?: string[];
|
||||
|
|
|
@ -108,6 +108,7 @@
|
|||
environmentId: props.environmentId as string,
|
||||
frontendDebug: executeType === 'localExec',
|
||||
reportId: reportId.value,
|
||||
apiDefinitionId: caseDetail.value.apiDefinitionId,
|
||||
};
|
||||
debugSocket(executeType); // 开启websocket
|
||||
if (!(caseDetail.value.id as string).startsWith('c') && executeType === 'serverExec') {
|
||||
|
|
Loading…
Reference in New Issue