refactor: ESB功能优化-ESB接口测试,使用ESB数据格式展现

ESB功能优化-测试ESB接口时使用ESB数据格式展现
This commit is contained in:
song-tianyang 2021-05-13 15:22:43 +08:00 committed by 刘瑞斌
parent 52143b1894
commit 4f937f9d11
6 changed files with 230 additions and 171 deletions

View File

@ -16,6 +16,7 @@ import io.metersphere.api.service.ApiTestEnvironmentService;
import io.metersphere.api.service.EsbApiParamService;
import io.metersphere.api.service.EsbImportService;
import io.metersphere.base.domain.ApiDefinition;
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs;
import io.metersphere.base.domain.Schedule;
import io.metersphere.commons.constants.RoleConstants;
@ -100,9 +101,9 @@ public class ApiDefinitionController {
@PostMapping(value = "/update", consumes = {"multipart/form-data"})
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER}, logical = Logical.OR)
public void update(@RequestPart("request") SaveApiDefinitionRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
public ApiDefinitionWithBLOBs update(@RequestPart("request") SaveApiDefinitionRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
checkPermissionService.checkProjectOwner(request.getProjectId());
apiDefinitionService.update(request, bodyFiles);
return apiDefinitionService.update(request, bodyFiles);
}
@GetMapping("/delete/{id}")

View File

@ -173,7 +173,7 @@ public class ApiDefinitionService {
FileUtils.createBodyFiles(bodyUploadIds, bodyFiles);
}
public void update(SaveApiDefinitionRequest request, List<MultipartFile> bodyFiles) {
public ApiDefinitionWithBLOBs update(SaveApiDefinitionRequest request, List<MultipartFile> bodyFiles) {
if (request.getRequest() != null) {
deleteFileByTestId(request.getRequest().getId());
}
@ -182,8 +182,9 @@ public class ApiDefinitionService {
if (StringUtils.equals(request.getProtocol(), "DUBBO")) {
request.setMethod("dubbo://");
}
updateTest(request);
ApiDefinitionWithBLOBs returnModel = updateTest(request);
FileUtils.createBodyFiles(bodyUploadIds, bodyFiles);
return returnModel;
}
public void delete(String apiId) {
@ -274,7 +275,7 @@ public class ApiDefinitionService {
}
private ApiDefinition updateTest(SaveApiDefinitionRequest request) {
private ApiDefinitionWithBLOBs updateTest(SaveApiDefinitionRequest request) {
checkNameExist(request);
if (StringUtils.equals(request.getMethod(), "ESB")) {
//ESB的接口类型数据采用TCP方式去发送并将方法类型改为TCP 并修改发送数据
@ -546,6 +547,8 @@ public class ApiDefinitionService {
* @return
*/
public String run(RunDefinitionRequest request, List<MultipartFile> bodyFiles) {
//检查是否是ESB请求ESB请求需要根据数据结构更换参数
request = esbApiParamService.checkIsEsbRequest(request);
int count = 100;
BaseSystemConfigDTO dto = systemParameterService.getBaseInfo();
if (StringUtils.isNotEmpty(dto.getConcurrency())) {

View File

@ -5,17 +5,16 @@ import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.automation.EsbDataStruct;
import io.metersphere.api.dto.automation.SaveApiScenarioRequest;
import io.metersphere.api.dto.automation.parse.EsbDataParser;
import io.metersphere.api.dto.definition.ApiDefinitionResult;
import io.metersphere.api.dto.definition.ApiTestCaseResult;
import io.metersphere.api.dto.definition.SaveApiDefinitionRequest;
import io.metersphere.api.dto.definition.SaveApiTestCaseRequest;
import io.metersphere.api.dto.definition.*;
import io.metersphere.api.dto.definition.request.MsTestElement;
import io.metersphere.api.dto.definition.request.MsTestPlan;
import io.metersphere.api.dto.definition.request.sampler.MsTCPSampler;
import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
import io.metersphere.base.domain.EsbApiParamsExample;
import io.metersphere.base.domain.EsbApiParamsWithBLOBs;
import io.metersphere.base.mapper.EsbApiParamsMapper;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -400,4 +399,33 @@ public class EsbApiParamService {
}
}
}
public RunDefinitionRequest checkIsEsbRequest(RunDefinitionRequest request) {
try {
//修改reqeust.parameters
//用户交互感受ESB的发送数据以报文模板为主框架同时前端不再有key-value的表格数据填充
//业务逻辑 发送ESB接口数据时使用报文模板中的数据同时报文模板中的${取值}目的是为了拼接数据结构(比如xml的子节点)
//代码实现: 此处打算解析前端传来的EsbDataStruct数据结构将数据结构按照报文模板中的${取值}为最高优先级组装keyValue对象这样Jmeter会自动拼装为合适的xml
if(request.getTestElement() != null ){
MsTestPlan testPlan = (MsTestPlan) request.getTestElement();
if(CollectionUtils.isNotEmpty(testPlan.getHashTree())){
for (MsTestElement testElement: testPlan.getHashTree()) {
if(CollectionUtils.isNotEmpty(testElement.getHashTree())){
for (MsTestElement apiElement:testElement.getHashTree()) {
if(apiElement instanceof MsTCPSampler){
MsTCPSampler tcpSampler = (MsTCPSampler) apiElement;
tcpSampler.setProtocol("ESB");
List<KeyValue> keyValueList = this.genKeyValueListByDataStruct(tcpSampler, tcpSampler.getEsbDataStruct());
tcpSampler.setParameters(keyValueList);
}
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return request;
}
}

View File

@ -215,7 +215,7 @@
selectDataRange: 'all',
showCasePage: true,
apiDefaultTab: 'default',
currentProtocol: null,
currentProtocol: 'HTTP',
currentModule: null,
selectNodeIds: [],
currentApi: {},
@ -260,7 +260,7 @@
});
},
'$route'(to, from) { // ctrl s
if (to.path.indexOf('/api/definition') == -1) {
if (to.path.indexOf('/api/definition') === -1) {
if (this.$refs && this.$refs.apiConfig) {
this.$refs.apiConfig.forEach(item => {
item.removeListener();
@ -299,7 +299,7 @@
}); // tab ctrl + s
let tabs = this.apiTabs;
let index = tabs.findIndex(item => item.name === tab.name); // tabindex
if (index != -1 && this.$refs.apiConfig[index - 1]) {
if (index !== -1 && this.$refs.apiConfig[index - 1]) {
this.$refs.apiConfig[index - 1].addListener(); // tab ctrl + s index-1tab
}
}

View File

@ -101,9 +101,11 @@ export default {
runTest(data) {
this.setParameters(data);
let bodyFiles = this.getBodyUploadFiles(data);
this.$fileUpload(this.reqUrl, null, bodyFiles, data, () => {
this.$fileUpload(this.reqUrl, null, bodyFiles, data, response => {
this.$success(this.$t('commons.save_success'));
this.reqUrl = "/api/definition/update";
let newData = response.data;
data.request = JSON.parse(newData.request);
this.$emit('runTest', data);
});
},

View File

@ -26,19 +26,32 @@
<environment-select :type="'TCP'" :current-data="api" :project-id="projectId"/>
</el-form-item>
<p class="tip">{{$t('api_test.definition.request.req_param')}} </p>
<!-- TCP 请求参数 -->
<ms-basis-parameters :request="api.request" @callback="runTest" ref="requestForm"/>
<!-- TCP 请求参数 -->
<!-- <p class="tip">{{$t('api_test.definition.request.req_param')}} </p>-->
<!-- <ms-basis-parameters :request="api.request" @callback="runTest" ref="requestForm"/>-->
<div v-if="api.method=='TCP'">
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
<ms-basis-parameters :request="api.request" @callback="runTest" ref="requestForm"/>
<!--返回结果-->
<!-- HTTP 请求返回数据 -->
<p class="tip">{{$t('api_test.definition.request.res_param')}} </p>
<ms-request-result-tail :response="responseData" ref="runResult"/>
</div>
<div v-else-if="api.method=='ESB'">
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
<esb-definition v-xpack v-if="showXpackCompnent" :show-script="true" :request="api.request" @callback="runTest" ref="requestForm"/>
</div>
</el-form>
<!--返回结果-->
<!-- HTTP 请求返回数据 -->
<p class="tip">{{$t('api_test.definition.request.res_param')}} </p>
<ms-request-result-tail :response="responseData" ref="runResult"/>
<ms-jmx-step :request="api.request" :response="responseData"/>
<div v-if="api.method=='ESB'">
<p class="tip">{{$t('api_test.definition.request.res_param')}}</p>
<esb-definition-response v-xpack v-if="showXpackCompnent" :is-api-component="false" :show-options-button="false" :request="api.request" :response-data="responseData" />
</div>
</el-card>
<!-- 加载用例 -->
@ -65,7 +78,9 @@ import MsBasisParameters from "../request/tcp/TcpBasisParameters";
import {REQ_METHOD} from "../../model/JsonData";
import EnvironmentSelect from "../environment/EnvironmentSelect";
import MsJmxStep from "../step/JmxStep";
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
const esbDefinition = (requireComponent!=null&&requireComponent.keys().length) > 0 ? requireComponent("./apidefinition/EsbDefinition.vue") : {};
const esbDefinitionResponse = (requireComponent!=null&&requireComponent.keys().length) > 0 ? requireComponent("./apidefinition/EsbDefinitionResponse.vue") : {};
export default {
name: "RunTestTCPPage",
components: {
@ -77,168 +92,178 @@ export default {
MsBottomContainer,
MsRequestResultTail,
MsRun,
MsBasisParameters
},
data() {
return {
visible: false,
api: {},
loaded: false,
loading: false,
currentRequest: {},
responseData: {type: 'HTTP', responseResult: {}, subRequestResults: []},
reqOptions: REQ_METHOD,
environments: [],
refreshSign: "",
createCase: "",
rules: {
environmentId: [{required: true, message: this.$t('api_test.definition.request.run_env'), trigger: 'change'}],
},
runData: [],
reportId: "",
MsBasisParameters,
"esbDefinition": esbDefinition.default,
"esbDefinitionResponse": esbDefinitionResponse.default
},
data() {
return {
visible: false,
api: {},
loaded: false,
loading: false,
currentRequest: {},
responseData: {type: 'HTTP', responseResult: {}, subRequestResults: []},
reqOptions: REQ_METHOD,
environments: [],
refreshSign: "",
createCase: "",
rules: {
environmentId: [{required: true, message: this.$t('api_test.definition.request.run_env'), trigger: 'change'}],
},
runData: [],
reportId: "",
showXpackCompnent:false,
}
},
props: {apiData: {}, currentProtocol: String,syncTabs: Array, projectId: String},
methods: {
handleCommand(e) {
switch (e) {
case "load_case":
return this.loadCase();
case "save_as_case":
return this.saveAsCase();
case "update_api":
return this.updateApi();
case "save_as_api":
return this.saveAsApi();
default:
return this.$refs['requestForm'].validate();
}
},
props: {apiData: {}, currentProtocol: String,syncTabs: Array, projectId: String},
methods: {
handleCommand(e) {
switch (e) {
case "load_case":
return this.loadCase();
case "save_as_case":
return this.saveAsCase();
case "update_api":
return this.updateApi();
case "save_as_api":
return this.saveAsApi();
default:
return this.$refs['requestForm'].validate();
refresh(){
this.$emit('refresh');
},
runTest() {
this.$refs['apiData'].validate((valid) => {
if (valid) {
this.loading = true;
this.api.request.name = this.api.id;
this.api.protocol = this.currentProtocol;
this.runData = [];
this.runData.push(this.api.request);
/*触发执行操作*/
this.reportId = getUUID().substring(0, 8);
}
},
refresh(){
this.$emit('refresh');
},
runTest() {
this.$refs['apiData'].validate((valid) => {
if (valid) {
this.loading = true;
this.api.request.name = this.api.id;
this.api.protocol = this.currentProtocol;
this.runData = [];
this.runData.push(this.api.request);
/*触发执行操作*/
this.reportId = getUUID().substring(0, 8);
}
})
},
runRefresh(data) {
this.responseData = data;
this.loading = false;
},
saveAs() {
this.$emit('saveAs', this.api);
},
loadCase() {
this.refreshSign = getUUID();
this.$refs.caseList.open();
this.visible = true;
},
apiCaseClose() {
this.visible = false;
},
getBodyUploadFiles() {
let bodyUploadFiles = [];
this.api.bodyUploadIds = [];
let request = this.api.request;
if (request.body) {
request.body.kvs.forEach(param => {
if (param.files) {
param.files.forEach(item => {
if (item.file) {
let fileId = getUUID().substring(0, 8);
item.name = item.file.name;
item.id = fileId;
this.api.bodyUploadIds.push(fileId);
bodyUploadFiles.push(item.file);
}
});
}
});
}
return bodyUploadFiles;
},
saveAsCase() {
this.createCase = getUUID();
this.$refs.caseList.open();
this.loaded = false;
},
saveAsApi() {
let data = {};
let req = this.api.request;
req.id = getUUID();
data.request = JSON.stringify(req);
data.method = this.api.method;
data.status = this.api.status;
data.userId = this.api.userId;
data.description = this.api.description;
this.$emit('saveAsApi', data);
this.$emit('refresh');
},
updateApi() {
let url = "/api/definition/update";
let bodyFiles = this.getBodyUploadFiles();
this.$fileUpload(url, null, bodyFiles, this.api, () => {
this.$success(this.$t('commons.save_success'));
if (this.syncTabs.indexOf(this.api.id) === -1) {
this.syncTabs.push(this.api.id);
}
this.$emit('saveApi', this.api);
});
},
selectTestCase(item) {
if (item != null) {
this.api.request = item.request;
} else {
this.api.request = this.currentRequest;
}
},
getResult() {
let url = "/api/definition/report/getReport/" + this.api.id;
this.$get(url, response => {
if (response.data) {
let data = JSON.parse(response.data.content);
this.responseData = data;
})
},
runRefresh(data) {
this.responseData = data;
this.loading = false;
},
saveAs() {
this.$emit('saveAs', this.api);
},
loadCase() {
this.refreshSign = getUUID();
this.$refs.caseList.open();
this.visible = true;
},
apiCaseClose() {
this.visible = false;
},
getBodyUploadFiles() {
let bodyUploadFiles = [];
this.api.bodyUploadIds = [];
let request = this.api.request;
if (request.body) {
request.body.kvs.forEach(param => {
if (param.files) {
param.files.forEach(item => {
if (item.file) {
let fileId = getUUID().substring(0, 8);
item.name = item.file.name;
item.id = fileId;
this.api.bodyUploadIds.push(fileId);
bodyUploadFiles.push(item.file);
}
});
}
});
}
return bodyUploadFiles;
},
created() {
//
this.api = JSON.parse(JSON.stringify(this.apiData));
this.api.protocol = this.currentProtocol;
this.currentRequest = this.api.request;
this.getResult();
saveAsCase() {
this.createCase = getUUID();
this.$refs.caseList.open();
this.loaded = false;
},
saveAsApi() {
let data = {};
let req = this.api.request;
req.id = getUUID();
data.request = JSON.stringify(req);
data.method = this.api.method;
data.status = this.api.status;
data.userId = this.api.userId;
data.description = this.api.description;
this.$emit('saveAsApi', data);
this.$emit('refresh');
},
updateApi() {
let url = "/api/definition/update";
let bodyFiles = this.getBodyUploadFiles();
if(this.api.method==='ESB'){
this.api.esbDataStruct = JSON.stringify(this.api.request.esbDataStruct);
this.api.backEsbDataStruct = JSON.stringify(this.api.request.backEsbDataStruct);
}
this.$fileUpload(url, null, bodyFiles, this.api, () => {
this.$success(this.$t('commons.save_success'));
if (this.syncTabs.indexOf(this.api.id) === -1) {
this.syncTabs.push(this.api.id);
}
this.$emit('saveApi', this.api);
});
},
selectTestCase(item) {
if (item != null) {
this.api.request = item.request;
} else {
this.api.request = this.currentRequest;
}
},
getResult() {
let url = "/api/definition/report/getReport/" + this.api.id;
this.$get(url, response => {
if (response.data) {
let data = JSON.parse(response.data.content);
this.responseData = data;
}
});
}
},
created() {
//
this.api = JSON.parse(JSON.stringify(this.apiData));
this.api.protocol = this.currentProtocol;
this.currentRequest = this.api.request;
this.getResult();
if (requireComponent != null && JSON.stringify(esbDefinition) !== '{}') {
this.showXpackCompnent = true;
}
}
}
</script>
<style scoped>
.ms-htt-width {
width: 350px;
}
.ms-htt-width {
width: 350px;
}
.environment-button {
margin-left: 20px;
padding: 7px;
}
.environment-button {
margin-left: 20px;
padding: 7px;
}
.tip {
padding: 3px 5px;
font-size: 16px;
border-radius: 4px;
border-left: 4px solid #783887;
}
.tip {
padding: 3px 5px;
font-size: 16px;
border-radius: 4px;
border-left: 4px solid #783887;
}
/deep/ .el-drawer {
overflow: auto;
}
/deep/ .el-drawer {
overflow: auto;
}
</style>