refactor(接口测试): 优化执行环境的JSON反序列化方法

This commit is contained in:
fit2-zhao 2022-10-15 19:37:02 +08:00 committed by fit2-zhao
parent 056ee6e982
commit 88622fa526
17 changed files with 231 additions and 42 deletions

View File

@ -23,6 +23,7 @@ import io.metersphere.api.dto.definition.request.variable.ScenarioVariable;
import io.metersphere.api.dto.scenario.DatabaseConfig;
import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
import io.metersphere.api.dto.scenario.environment.item.EnvAssertions;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs;
import io.metersphere.base.domain.FileMetadata;
@ -926,4 +927,18 @@ public class ElementUtil {
}
}
}
public static List<MsAssertions> copyAssertion(List<EnvAssertions> envAssertions) {
List<MsAssertions> assertions = new LinkedList<>();
if (CollectionUtils.isNotEmpty(envAssertions)) {
envAssertions.forEach(item -> {
if (item != null) {
MsAssertions env = new MsAssertions();
BeanUtils.copyBean(env, item);
assertions.add(env);
}
});
}
return assertions;
}
}

View File

@ -10,27 +10,29 @@ import io.metersphere.api.dto.definition.request.variable.ScenarioVariable;
import io.metersphere.api.dto.mock.config.MockConfigStaticData;
import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
import io.metersphere.api.dto.scenario.environment.item.EnvJSR223Processor;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs;
import io.metersphere.base.mapper.ApiScenarioMapper;
import io.metersphere.commons.constants.ElementConstants;
import io.metersphere.commons.constants.MsTestElementConstants;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.FileUtils;
import io.metersphere.commons.utils.JSON;
import io.metersphere.commons.utils.JSONUtil;
import io.metersphere.constants.RunModeConstants;
import io.metersphere.environment.service.BaseEnvGroupProjectService;
import io.metersphere.environment.service.BaseEnvironmentService;
import io.metersphere.plugin.core.MsParameter;
import io.metersphere.plugin.core.MsTestElement;
import io.metersphere.commons.utils.JSONUtil;
import org.json.JSONObject;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.config.Arguments;
import org.apache.jorphan.collections.HashTree;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.LinkedList;
@ -163,7 +165,9 @@ public class MsScenario extends MsTestElement {
if (config.getConfig() != null && (this.variableEnable == null || this.variableEnable)) {
config.getConfig().forEach((k, environmentConfig) -> {
if (environmentConfig != null) {
MsJSR223Processor processor = isPre ? environmentConfig.getPreStepProcessor() : environmentConfig.getPostStepProcessor();
EnvJSR223Processor envProcessor = isPre ? environmentConfig.getPreStepProcessor() : environmentConfig.getPostStepProcessor();
MsJSR223Processor processor = new MsJSR223Processor();
BeanUtils.copyBean(processor, envProcessor);
if (processor != null && StringUtils.isNotEmpty(processor.getScript())) {
processor.setType(ElementConstants.JSR223);
processor.setClazzName(MsJSR223Processor.class.getCanonicalName());

View File

@ -8,6 +8,8 @@ import io.metersphere.api.dto.definition.request.ParameterConfig;
import io.metersphere.api.dto.definition.request.assertions.MsAssertions;
import io.metersphere.api.dto.definition.request.auth.MsAuthManager;
import io.metersphere.api.dto.definition.request.dns.MsDNSCacheManager;
import io.metersphere.api.dto.definition.request.processors.post.MsJSR223PostProcessor;
import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor;
import io.metersphere.api.dto.mock.MockApiHeaders;
import io.metersphere.api.dto.scenario.Body;
import io.metersphere.api.dto.scenario.HttpConfig;
@ -19,7 +21,12 @@ import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
import io.metersphere.commons.constants.ElementConstants;
import io.metersphere.commons.constants.MsTestElementConstants;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.*;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.FileUtils;
import io.metersphere.commons.utils.HashTreeUtil;
import io.metersphere.commons.utils.JSONUtil;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.environment.service.CommandService;
import io.metersphere.environment.ssl.KeyStoreConfig;
import io.metersphere.environment.ssl.KeyStoreFile;
@ -306,16 +313,28 @@ public class MsHTTPSamplerProxy extends MsTestElement {
if (environmentConfig != null) {
String useEvnId = environmentConfig.getEnvironmentId();
if (this.authManager == null && environmentConfig.getAuthManager() != null && environmentConfig.getAuthManager().getAuthManager() != null) {
this.authManager = environmentConfig.getAuthManager().getAuthManager();
MsAuthManager authManager = new MsAuthManager();
BeanUtils.copyBean(authManager, environmentConfig.getAuthManager().getAuthManager());
this.authManager = authManager;
}
if (StringUtils.isNotEmpty(useEvnId) && !StringUtils.equals(useEvnId, this.getEnvironmentId())) {
this.setEnvironmentId(useEvnId);
}
HttpConfig httpConfig = config.matchConfig(this);
httpConfig.setPreProcessor(environmentConfig.getPreProcessor());
httpConfig.setPostProcessor(environmentConfig.getPostProcessor());
if (environmentConfig.getPreProcessor() != null) {
MsJSR223PreProcessor msJSR223PreProcessor = new MsJSR223PreProcessor();
BeanUtils.copyBean(msJSR223PreProcessor, environmentConfig.getPreProcessor());
httpConfig.setPreProcessor(msJSR223PreProcessor);
}
if (environmentConfig.getPostProcessor() != null) {
MsJSR223PostProcessor postProcessor = new MsJSR223PostProcessor();
BeanUtils.copyBean(postProcessor, environmentConfig.getPostProcessor());
httpConfig.setPostProcessor(postProcessor);
}
httpConfig.setGlobalScriptConfig(environmentConfig.getGlobalScriptConfig());
httpConfig.setAssertions(environmentConfig.getAssertions());
if (CollectionUtils.isNotEmpty(environmentConfig.getAssertions())) {
httpConfig.setAssertions(ElementUtil.copyAssertion(environmentConfig.getAssertions()));
}
if (environmentConfig.isUseErrorCode()) {
httpConfig.setErrorReportAssertions(HashTreeUtil.getErrorReportByProjectId(this.getProjectId(), environmentConfig.isHigherThanSuccess(), environmentConfig.isHigherThanError()));
}

View File

@ -168,7 +168,7 @@ public class MsTCPSampler extends MsTestElement {
hashTree.forEach(el -> {
if (el instanceof MsAssertions && finalEnvConfig != null) {
//断言设置需要和全局断言误报进行去重
el = hashTreeUtil.duplicateRegexInAssertions(finalEnvConfig.getAssertions(), (MsAssertions) el);
el = hashTreeUtil.duplicateRegexInAssertions(ElementUtil.copyAssertion(finalEnvConfig.getAssertions()), (MsAssertions) el);
}
el.toHashTree(samplerHashTree, el.getHashTree(), config);
});

View File

@ -5,5 +5,5 @@ import lombok.Data;
@Data
public class EnvAuthManager {
private MsAuthManager authManager;
private EnvAuthManager authManager;
}

View File

@ -1,12 +1,13 @@
package io.metersphere.api.dto.scenario.environment;
import io.metersphere.api.dto.definition.request.assertions.MsAssertions;
import io.metersphere.api.dto.definition.request.processors.MsJSR223Processor;
import io.metersphere.api.dto.definition.request.processors.post.MsJSR223PostProcessor;
import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import io.metersphere.api.dto.scenario.DatabaseConfig;
import io.metersphere.api.dto.scenario.HttpConfig;
import io.metersphere.api.dto.scenario.TCPConfig;
import io.metersphere.api.dto.scenario.environment.item.EnvAssertions;
import io.metersphere.api.dto.scenario.environment.item.EnvJSR223PostProcessor;
import io.metersphere.api.dto.scenario.environment.item.EnvJSR223PreProcessor;
import io.metersphere.api.dto.scenario.environment.item.EnvJSR223Processor;
import io.metersphere.environment.ssl.KeyStoreConfig;
import lombok.Data;
@ -22,16 +23,17 @@ public class EnvironmentConfig {
private TCPConfig tcpConfig;
private KeyStoreConfig sslConfig;
//全局前后置脚本每个请求都跑一遍
private MsJSR223PreProcessor preProcessor;
private MsJSR223PostProcessor postProcessor;
private EnvJSR223PreProcessor preProcessor;
private EnvJSR223PostProcessor postProcessor;
//全局前后置脚本步骤只在全部步骤都前后做处理
private MsJSR223Processor preStepProcessor;
private MsJSR223Processor postStepProcessor;
private EnvJSR223Processor preStepProcessor;
private EnvJSR223Processor postStepProcessor;
//全局前后置脚本都配置
private GlobalScriptConfig globalScriptConfig;
private EnvAuthManager authManager;
private List<MsAssertions> assertions;
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS,include = JsonTypeInfo.As.WRAPPER_ARRAY,defaultImpl = EnvAssertions.class)
private List<EnvAssertions> assertions;
private boolean useErrorCode;
private boolean higherThanSuccess;
private boolean higherThanError;

View File

@ -0,0 +1,58 @@
package io.metersphere.api.dto.scenario.environment.item;
import io.metersphere.plugin.core.MsTestElement;
import lombok.Data;
import java.util.LinkedList;
@Data
public class BaseEnvElement {
// 组件类型
private String type;
// 用于数据反射对象
private String clazzName = MsTestElement.class.getCanonicalName();
// 自身资源ID用例ID/接口ID/场景ID)
private String id;
// 当前组件唯一标示
private String resourceId;
// 组件标签名称
private String name;
// 组件标签
private String label;
// 引用对象标示
private String referenced;
// 是否展开收起操作
private boolean active;
// 组件索引
private String index;
// 是否禁用/启用标示
private boolean enable = true;
// 引用对象类型REFCreated,DELETE
private String refType;
// 子组件
private LinkedList<MsTestElement> hashTree;
// 项目ID
private String projectId;
// 是否是mock环境
private boolean isMockEnvironment;
// 自身环境Id
private String environmentId;
// 插件ID
private String pluginId;
// 步骤别名
private String stepName;
}

View File

@ -0,0 +1,26 @@
package io.metersphere.api.dto.scenario.environment.item;
import io.metersphere.api.dto.definition.request.assertions.MsAssertionDuration;
import io.metersphere.api.dto.definition.request.assertions.MsAssertionJSR223;
import io.metersphere.api.dto.definition.request.assertions.MsAssertionJsonPath;
import io.metersphere.api.dto.definition.request.assertions.MsAssertionRegex;
import io.metersphere.api.dto.definition.request.assertions.MsAssertionXPath2;
import io.metersphere.api.dto.definition.request.assertions.document.MsAssertionDocument;
import io.metersphere.commons.constants.ElementConstants;
import lombok.Data;
import java.util.List;
@Data
public class EnvAssertions extends BaseEnvElement {
private String clazzName = EnvAssertions.class.getCanonicalName();
private boolean scenarioAss;
private List<MsAssertionRegex> regex;
private List<MsAssertionJsonPath> jsonPath;
private List<MsAssertionJSR223> jsr223;
private List<MsAssertionXPath2> xpath2;
private MsAssertionDuration duration;
private String type = ElementConstants.ASSERTIONS;
private MsAssertionDocument document;
}

View File

@ -0,0 +1,19 @@
package io.metersphere.api.dto.scenario.environment.item;
import io.metersphere.commons.constants.ElementConstants;
import lombok.Data;
@Data
public class EnvAuthManager extends BaseEnvElement {
private String type = ElementConstants.AUTH_MANAGER;
private String clazzName = EnvAuthManager.class.getCanonicalName();
private String username;
private String password;
private String url;
private String realm;
private String verification;
private String mechanism;
private String encrypt;
private String domain;
private String environment;
}

View File

@ -0,0 +1,12 @@
package io.metersphere.api.dto.scenario.environment.item;
import io.metersphere.commons.constants.ElementConstants;
import lombok.Data;
@Data
public class EnvJSR223PostProcessor extends BaseEnvElement {
private String type = ElementConstants.JSR223_POST;
private String clazzName = EnvJSR223PostProcessor.class.getCanonicalName();
private String script;
private String scriptLanguage;
}

View File

@ -0,0 +1,12 @@
package io.metersphere.api.dto.scenario.environment.item;
import io.metersphere.commons.constants.ElementConstants;
import lombok.Data;
@Data
public class EnvJSR223PreProcessor extends BaseEnvElement {
private String type = ElementConstants.JSR223_PRE;
private String clazzName = EnvJSR223PreProcessor.class.getCanonicalName();
private String script;
private String scriptLanguage;
}

View File

@ -0,0 +1,11 @@
package io.metersphere.api.dto.scenario.environment.item;
import io.metersphere.commons.constants.ElementConstants;
import lombok.Data;
@Data
public class EnvJSR223Processor extends BaseEnvElement {
private String type = ElementConstants.JSR223;
private String clazzName = EnvJSR223Processor.class.getCanonicalName();
private String script;
private String scriptLanguage;
}

View File

@ -7,6 +7,7 @@ import io.metersphere.api.dto.scenario.HttpConfig;
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
import io.metersphere.api.dto.scenario.environment.GlobalScriptConfig;
import io.metersphere.api.dto.scenario.environment.GlobalScriptFilterRequest;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.plugin.core.MsTestElement;
import org.apache.commons.lang3.StringUtils;
import org.apache.jorphan.collections.HashTree;
@ -33,7 +34,9 @@ public class JMeterScriptUtil {
public static MsJSR223PreProcessor getPreScript(EnvironmentConfig envConfig) {
if (envConfig != null && envConfig.getPreProcessor() != null && StringUtils.isNotEmpty(envConfig.getPreProcessor().getScript())) {
return envConfig.getPreProcessor();
MsJSR223PreProcessor preProcessor = new MsJSR223PreProcessor();
BeanUtils.copyBean(preProcessor,envConfig.getPreProcessor());
return preProcessor;
} else {
return null;
}
@ -41,7 +44,9 @@ public class JMeterScriptUtil {
public static MsJSR223PostProcessor getPostScript(EnvironmentConfig envConfig) {
if (envConfig != null && envConfig.getPostProcessor() != null && StringUtils.isNotEmpty(envConfig.getPostProcessor().getScript())) {
return envConfig.getPostProcessor();
MsJSR223PostProcessor post = new MsJSR223PostProcessor();
BeanUtils.copyBean(post,envConfig.getPostProcessor());
return post;
} else {
return null;
}

View File

@ -1,6 +1,7 @@
package io.metersphere.commons.utils;
import io.metersphere.api.dto.RunningParamKeys;
import io.metersphere.api.dto.definition.request.ElementUtil;
import io.metersphere.api.dto.definition.request.ParameterConfig;
import io.metersphere.api.dto.definition.request.assertions.MsAssertionRegex;
import io.metersphere.api.dto.definition.request.assertions.MsAssertions;
@ -221,7 +222,7 @@ public class HashTreeUtil {
}
}
if (CollectionUtils.isNotEmpty(envConfig.getAssertions())) {
for (MsAssertions assertion : envConfig.getAssertions()) {
for (MsAssertions assertion : ElementUtil.copyAssertion(envConfig.getAssertions())) {
assertion.toHashTree(samplerHashTree, assertion.getHashTree(), config);
}
}

View File

@ -1,7 +1,11 @@
package io.metersphere.commons.utils;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.metersphere.commons.constants.PropertyConstant;
@ -16,30 +20,30 @@ import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
public class JSONUtil {
private static final ObjectMapper objectMapper = new ObjectMapper();
static {
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 自动检测所有类的全部属性
objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
// 如果一个对象中没有任何的属性那么在序列化的时候就会报错
objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
}
/**
* 接地json字符串到实例对象
*
* @param clazz 和JSON对应的类的Class必须拥有setXxx()函数其中xxx为属性
* @param json 被解析的JSON字符串
* @return 返回传入的Object对象实例
*/
public static <T> T parseObject(String json, Class<T> clazz) {
public static <T> T parseObject(String content, Class<T> valueType) {
try {
JSONObject jsonObject = new JSONObject(json);
return parseObject(clazz, jsonObject);
} catch (Exception e) {
MSException.throwException("当前数据非JSON格式");
return objectMapper.readValue(content, valueType);
} catch (IOException e) {
throw new RuntimeException(e);
}
return null;
}
public static String toJSONString(Object value) {
@ -224,4 +228,6 @@ public class JSONUtil {
public static boolean isNotEmpty(JSONObject object) {
return object != null && object.length() > 0;
}
}

View File

@ -273,7 +273,11 @@ export default {
formatApi() {
if (this.currentApi.response != null && this.currentApi.response != 'null' && this.currentApi.response != undefined) {
if (Object.prototype.toString.call(this.currentApi.response).match(/\[object (\w+)\]/)[1].toLowerCase() !== 'object') {
this.currentApi.response = JSON.parse(this.currentApi.response);
try {
this.currentApi.response = JSON.parse(this.currentApi.response);
}catch (e){
this.currentApi.response = {};
}
}
}
if (this.currentApi.request != null && this.currentApi.request != 'null' && this.currentApi.request != undefined) {

View File

@ -735,11 +735,6 @@ export default {
if (!item.request.rest) {
item.request.rest = [];
} else if (item.request.rest.length === 1) {
let values = item.request.rest.filter(tab => tab.name !== '');
if (values.length > 0) {
item.request.rest.push(new KeyValue({enable: true}))
}
}
if (item.request.query && item.request.query.length === 1) {
let values = item.request.query.filter(tab => tab.name !== '');