refactor(接口测试): 支持动态注册子组件

This commit is contained in:
fit2-zhao 2023-11-03 18:32:58 +08:00 committed by Craftsman
parent 7e5a86f881
commit f34c916760
3 changed files with 73 additions and 15 deletions

View File

@ -9,6 +9,5 @@ import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@PluginSubType("MsLoopController") @PluginSubType("MsLoopController")
public class MsLoopController extends TestElementDTO { public class MsLoopController extends TestElementDTO {
private String clazzName = MsLoopController.class.getCanonicalName();
private String loopType; private String loopType;
} }

View File

@ -9,7 +9,6 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.json.JsonMapper; import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.jsontype.NamedType; import com.fasterxml.jackson.databind.jsontype.NamedType;
import com.fasterxml.jackson.databind.jsontype.impl.StdSubtypeResolver;
import com.fasterxml.jackson.databind.type.CollectionType; import com.fasterxml.jackson.databind.type.CollectionType;
import io.metersphere.sdk.dto.api.request.post.processors.MsPostJSR223Processor; import io.metersphere.sdk.dto.api.request.post.processors.MsPostJSR223Processor;
import io.metersphere.sdk.dto.api.request.sampler.MsDebugSampler; import io.metersphere.sdk.dto.api.request.sampler.MsDebugSampler;
@ -24,18 +23,23 @@ public class ApiDataUtils {
private ApiDataUtils() { private ApiDataUtils() {
} }
private static final ObjectMapper objectMapper = JsonMapper.builder() private static ObjectMapper objectMapper = JsonMapper.builder()
.enable(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS) .enable(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS)
.build(); .build();
private static final StdSubtypeResolver resolver = new StdSubtypeResolver(); // 默认内置子组件如果有新的子组件需要在这里添加
static final List<NamedType> namedTypes = new LinkedList<>();
static { static {
// 添加处理资源文件的类 // 默认内置的子组件
final List<NamedType> namedTypes = new LinkedList<>();
namedTypes.add(new NamedType(MsPostJSR223Processor.class, MsPostJSR223Processor.class.getSimpleName())); namedTypes.add(new NamedType(MsPostJSR223Processor.class, MsPostJSR223Processor.class.getSimpleName()));
namedTypes.add(new NamedType(MsDebugSampler.class, MsDebugSampler.class.getSimpleName())); namedTypes.add(new NamedType(MsDebugSampler.class, MsDebugSampler.class.getSimpleName()));
setObjectMapper(objectMapper);
namedTypes.forEach(objectMapper::registerSubtypes);
}
private static void setObjectMapper(ObjectMapper objectMapper) {
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 支持json字符中带注释符 // 支持json字符中带注释符
objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true); objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
@ -44,8 +48,6 @@ public class ApiDataUtils {
// 如果一个对象中没有任何的属性那么在序列化的时候就会报错 // 如果一个对象中没有任何的属性那么在序列化的时候就会报错
objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
namedTypes.forEach(resolver::registerSubtypes);
objectMapper.setSubtypeResolver(resolver);
} }
public static String toJSONString(Object value) { public static String toJSONString(Object value) {
@ -88,11 +90,23 @@ public class ApiDataUtils {
/** /**
* 设置动态加载的jar的Resolver * 设置动态加载的jar的Resolver
* *
* @param namedTypes PluginSubType 注解的类 * @param newTypes PluginSubType 注解的类
*/ */
public static void setResolver(List<NamedType> namedTypes) { public static void setResolver(List<NamedType> newTypes) {
namedTypes.forEach(resolver::registerSubtypes); // 获取所有子组件 TODO此方法无法卸载组件
objectMapper.setSubtypeResolver(resolver); // SubtypeResolver subtypeResolver = objectMapper.getSubtypeResolver();
// objectMapper.setSubtypeResolver(subtypeResolver);
objectMapper = JsonMapper.builder()
.enable(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS)
.build();
setObjectMapper(objectMapper);
// 加入默认组件
namedTypes.forEach(objectMapper::registerSubtypes);
// 加入新的动态组件
newTypes.forEach(objectMapper::registerSubtypes);
} }
/** /**
@ -101,7 +115,8 @@ public class ApiDataUtils {
* @param clazz PluginSubType 注解的类 * @param clazz PluginSubType 注解的类
*/ */
public static void setResolver(Class<?> clazz) { public static void setResolver(Class<?> clazz) {
resolver.registerSubtypes(clazz); setResolver(new LinkedList<>());
objectMapper.setSubtypeResolver(resolver); // 加入新的动态组件
objectMapper.registerSubtypes(clazz);
} }
} }

View File

@ -1,7 +1,9 @@
package io.metersphere.api.controller; package io.metersphere.api.controller;
import com.fasterxml.jackson.databind.jsontype.NamedType;
import io.metersphere.api.util.ApiDataUtils; import io.metersphere.api.util.ApiDataUtils;
import io.metersphere.plugin.api.dto.TestElementDTO; import io.metersphere.plugin.api.dto.TestElementDTO;
import io.metersphere.sdk.dto.api.request.logic.controller.MsLoopController;
import io.metersphere.sdk.dto.api.request.post.processors.MsPostJSR223Processor; import io.metersphere.sdk.dto.api.request.post.processors.MsPostJSR223Processor;
import io.metersphere.sdk.dto.api.request.sampler.MsDebugSampler; import io.metersphere.sdk.dto.api.request.sampler.MsDebugSampler;
import io.metersphere.system.uid.IDGenerator; import io.metersphere.system.uid.IDGenerator;
@ -10,13 +12,15 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMock
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List;
@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@AutoConfigureMockMvc @AutoConfigureMockMvc
public class PluginSubTypeTests { public class PluginSubTypeTests {
@Test @Test
@Order(0) @Order(0)
public void pluginSubTypeTest() throws Exception { public void pluginSubTypeTest() throws Exception {
@ -35,4 +39,44 @@ public class PluginSubTypeTests {
TestElementDTO testElementDTO = ApiDataUtils.parseObject(json, TestElementDTO.class); TestElementDTO testElementDTO = ApiDataUtils.parseObject(json, TestElementDTO.class);
Assertions.assertNotNull(testElementDTO); Assertions.assertNotNull(testElementDTO);
} }
@Test
@Order(1)
public void resolverTest() throws Exception {
// ApiDataUtils.setResolver(MsLoopController.class);
List<NamedType> namedTypes = new LinkedList<>();
namedTypes.add(new NamedType(MsLoopController.class, MsLoopController.class.getSimpleName()));
ApiDataUtils.setResolver(namedTypes);
}
@Test
@Order(2)
public void newPluginSubTypeTest() throws Exception {
MsLoopController loopController = new MsLoopController();
loopController.setName("测试loopController");
String json = ApiDataUtils.toJSONString(loopController);
TestElementDTO testElementDTO = ApiDataUtils.parseObject(json, TestElementDTO.class);
Assertions.assertNotNull(testElementDTO);
}
@Test
@Order(3)
public void retrySubTypeTest() throws Exception {
MsDebugSampler debugSampler = new MsDebugSampler();
debugSampler.setName("测试DebugSampler");
debugSampler.setUuid(IDGenerator.nextStr());
LinkedList<TestElementDTO> hashTree = new LinkedList<>();
hashTree.add(debugSampler);
MsPostJSR223Processor msjsr223Processor = new MsPostJSR223Processor();
msjsr223Processor.setName("测试jsr223");
msjsr223Processor.setJsrEnable(true);
msjsr223Processor.setChildren(hashTree);
String json = ApiDataUtils.toJSONString(msjsr223Processor);
Assertions.assertNotNull(json);
TestElementDTO testElementDTO = ApiDataUtils.parseObject(json, TestElementDTO.class);
Assertions.assertNotNull(testElementDTO);
}
} }