From d6f633062bb356ce3438481b9c8a5722da5dfa05 Mon Sep 17 00:00:00 2001 From: AgAngle <1323481023@qq.com> Date: Thu, 25 Jan 2024 11:51:56 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=8E=A5=E5=8F=A3=E6=B5=8B=E8=AF=95):=20?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E6=8F=92=E4=BB=B6=E8=A1=A8=E5=8D=95=E4=B8=8B?= =?UTF-8?q?=E6=8B=89=E6=A1=86=E9=80=89=E9=A1=B9=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/dto/ApiPluginOptionsRequest.java | 26 +++++++ .../plugin/api/dto/ApiPluginSelectOption.java | 19 +++++ .../plugin/api/spi/AbstractApiPlugin.java | 18 +++++ .../src/main/resources/i18n/api.properties | 1 + .../main/resources/i18n/api_en_US.properties | 3 +- .../main/resources/i18n/api_zh_CN.properties | 1 + .../main/resources/i18n/api_zh_TW.properties | 3 +- .../api/controller/ApiTestController.java | 15 ++++ .../api/dto/ApiTestPluginOptionRequest.java | 37 ++++++++++ .../api/service/ApiTestService.java | 22 ++++++ .../controller/ApiTestControllerTests.java | 67 ++++++++++++++++++ .../api/controller/ApiTestServiceTest.java | 1 + .../file/dubbo-option-test-sampler-v3.x.jar | Bin 0 -> 4297 bytes .../metersphere/system/dto/ProtocolDTO.java | 4 ++ .../system/service/ApiPluginService.java | 35 ++++++--- .../system/service/ApiPluginServiceTests.java | 1 + 16 files changed, 241 insertions(+), 12 deletions(-) create mode 100644 backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/dto/ApiPluginOptionsRequest.java create mode 100644 backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/dto/ApiPluginSelectOption.java create mode 100644 backend/services/api-test/src/main/java/io/metersphere/api/dto/ApiTestPluginOptionRequest.java create mode 100644 backend/services/api-test/src/test/resources/file/dubbo-option-test-sampler-v3.x.jar diff --git a/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/dto/ApiPluginOptionsRequest.java b/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/dto/ApiPluginOptionsRequest.java new file mode 100644 index 0000000000..7cb78189af --- /dev/null +++ b/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/dto/ApiPluginOptionsRequest.java @@ -0,0 +1,26 @@ +package io.metersphere.plugin.api.dto; + +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; + +/** + * @author wx + */ +@Setter +@Getter +public class ApiPluginOptionsRequest implements Serializable { + private static final long serialVersionUID = 1L; + /** + * 方法所需的查询参数 + * 例如: + * 查询的过滤条件 + * 级联的情况,需要表单的其他参数值等 + */ + private Object queryParam; + /** + * 需要调用的插件方法 + */ + private String optionMethod; +} diff --git a/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/dto/ApiPluginSelectOption.java b/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/dto/ApiPluginSelectOption.java new file mode 100644 index 0000000000..7ad8962332 --- /dev/null +++ b/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/dto/ApiPluginSelectOption.java @@ -0,0 +1,19 @@ +package io.metersphere.plugin.api.dto; + +import lombok.Data; + +/** + * @Author: jianxing + * @CreateTime: 2024-01-24 17:47 + */ +@Data +public class ApiPluginSelectOption { + /** + * 选项名称 + */ + private String text; + /** + * 选项值 + */ + private String value; +} diff --git a/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/spi/AbstractApiPlugin.java b/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/spi/AbstractApiPlugin.java index 500dd7133c..b47178d0ba 100644 --- a/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/spi/AbstractApiPlugin.java +++ b/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/spi/AbstractApiPlugin.java @@ -1,9 +1,27 @@ package io.metersphere.plugin.api.spi; +import io.metersphere.plugin.api.dto.ApiPluginOptionsRequest; +import io.metersphere.plugin.api.dto.ApiPluginSelectOption; import io.metersphere.plugin.sdk.spi.AbstractMsPlugin; +import io.metersphere.plugin.sdk.util.MSPluginException; + +import java.lang.reflect.InvocationTargetException; +import java.util.List; /** * 接口插件抽象类 */ public abstract class AbstractApiPlugin extends AbstractMsPlugin { + + public List getPluginOptions(ApiPluginOptionsRequest request) { + String method = request.getOptionMethod(); + try { + // 这里反射调用插件方法,获取下拉框选项 + return (List) this.getClass().getMethod(method, request.getClass()).invoke(this, request); + } catch (InvocationTargetException e) { + throw new MSPluginException(e.getTargetException()); + } catch (Exception e) { + throw new MSPluginException(e); + } + } } diff --git a/backend/framework/sdk/src/main/resources/i18n/api.properties b/backend/framework/sdk/src/main/resources/i18n/api.properties index 396223269c..a72a263daf 100644 --- a/backend/framework/sdk/src/main/resources/i18n/api.properties +++ b/backend/framework/sdk/src/main/resources/i18n/api.properties @@ -379,4 +379,5 @@ api_scenario_exist=场景已存在 schedule_not_exist=定时任务不存在 api_case_report_not_exist=用例报告不存在 api_scenario_report_not_exist=场景报告不存在 +permission.api_plugin.name=接口插件 diff --git a/backend/framework/sdk/src/main/resources/i18n/api_en_US.properties b/backend/framework/sdk/src/main/resources/i18n/api_en_US.properties index b3643eac8d..3895ce2a58 100644 --- a/backend/framework/sdk/src/main/resources/i18n/api_en_US.properties +++ b/backend/framework/sdk/src/main/resources/i18n/api_en_US.properties @@ -390,4 +390,5 @@ api_swagger_url_error=Swagger url unable to connect api_scenario_exist=The scenario already exists schedule_not_exist=The scheduled task does not exist api_case_report_not_exist=Api report does not exist -api_scenario_report_not_exist=Scenario report does not exist \ No newline at end of file +api_scenario_report_not_exist=Scenario report does not exist +permission.api_plugin.name=Api Plugin \ No newline at end of file diff --git a/backend/framework/sdk/src/main/resources/i18n/api_zh_CN.properties b/backend/framework/sdk/src/main/resources/i18n/api_zh_CN.properties index 1d462a185d..e83f4f2780 100644 --- a/backend/framework/sdk/src/main/resources/i18n/api_zh_CN.properties +++ b/backend/framework/sdk/src/main/resources/i18n/api_zh_CN.properties @@ -360,3 +360,4 @@ api_scenario_exist=场景已存在 schedule_not_exist=定时任务不存在 api_case_report_not_exist=用例报告不存在 api_scenario_report_not_exist=场景报告不存在 +permission.api_plugin.name=接口插件 \ No newline at end of file diff --git a/backend/framework/sdk/src/main/resources/i18n/api_zh_TW.properties b/backend/framework/sdk/src/main/resources/i18n/api_zh_TW.properties index 12ba46d80c..006a05108c 100644 --- a/backend/framework/sdk/src/main/resources/i18n/api_zh_TW.properties +++ b/backend/framework/sdk/src/main/resources/i18n/api_zh_TW.properties @@ -359,4 +359,5 @@ api_swagger_url_error=Swagger url無法調解 api_scenario_exist=場景已存在 schedule_not_exist=定時任務不存在 api_case_report_not_exist=用例報告不存在 -api_scenario_report_not_exist=場景報告不存在 \ No newline at end of file +api_scenario_report_not_exist=場景報告不存在 +permission.api_plugin.name=接口插件 \ No newline at end of file diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/controller/ApiTestController.java b/backend/services/api-test/src/main/java/io/metersphere/api/controller/ApiTestController.java index c9399dba26..feef5c6b87 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/controller/ApiTestController.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/controller/ApiTestController.java @@ -1,14 +1,17 @@ package io.metersphere.api.controller; +import io.metersphere.api.dto.ApiTestPluginOptionRequest; import io.metersphere.api.service.ApiExecuteService; import io.metersphere.api.service.ApiTestService; import io.metersphere.jmeter.mock.Mock; +import io.metersphere.plugin.api.dto.ApiPluginSelectOption; import io.metersphere.project.dto.customfunction.request.CustomFunctionRunRequest; import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.system.dto.ProtocolDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; +import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -48,4 +51,16 @@ public class ApiTestController { public String run(@Validated @RequestBody CustomFunctionRunRequest runRequest) { return apiExecuteService.runScript(runRequest); } + + @PostMapping("/plugin/form/option") + @Operation(summary = "接口测试-获取插件表单选项") + @RequiresPermissions(value = { + PermissionConstants.PROJECT_API_DEFINITION_READ, + PermissionConstants.PROJECT_API_DEFINITION_CASE_READ, + PermissionConstants.PROJECT_API_DEBUG_READ, + PermissionConstants.PROJECT_API_SCENARIO_READ + }, logical = Logical.OR) + public List getFormOptions(@Validated @RequestBody ApiTestPluginOptionRequest request) { + return apiTestService.getFormOptions(request); + } } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/ApiTestPluginOptionRequest.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/ApiTestPluginOptionRequest.java new file mode 100644 index 0000000000..db8e92fd73 --- /dev/null +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/ApiTestPluginOptionRequest.java @@ -0,0 +1,37 @@ +package io.metersphere.api.dto; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; +import lombok.Data; + +@Data +public class ApiTestPluginOptionRequest { + /** + * 组织ID + */ + @NotBlank + @Size(max = 50) + private String orgId; + + /** + * 插件ID + */ + @NotBlank + @Size(max = 50) + private String pluginId; + + /** + * 需要调用的插件方法 + */ + @NotBlank + @Size(max = 100) + private String optionMethod; + + /** + * 方法所需的查询参数 + * 例如: + * 查询的过滤条件 + * 级联的情况,需要表单的其他参数值等 + */ + private Object queryParam; +} diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiTestService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiTestService.java index 80394f9697..fccfabaa0c 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiTestService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiTestService.java @@ -1,9 +1,17 @@ package io.metersphere.api.service; +import io.metersphere.api.dto.ApiTestPluginOptionRequest; import io.metersphere.api.dto.request.http.MsHTTPElement; +import io.metersphere.plugin.api.dto.ApiPluginOptionsRequest; +import io.metersphere.plugin.api.dto.ApiPluginSelectOption; +import io.metersphere.plugin.api.spi.AbstractApiPlugin; +import io.metersphere.sdk.util.BeanUtils; import io.metersphere.system.dto.ProtocolDTO; import io.metersphere.system.service.ApiPluginService; +import io.metersphere.system.utils.ServiceUtils; import jakarta.annotation.Resource; +import org.apache.commons.lang3.StringUtils; +import org.pf4j.PluginWrapper; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -31,4 +39,18 @@ public class ApiTestService { return protocols; } + public List getFormOptions(ApiTestPluginOptionRequest request) { + // 获取组织下有权限的接口插件 + List pluginWrappers = apiPluginService.getOrgApiPluginWrappers(request.getOrgId()); + PluginWrapper pluginWrapper = pluginWrappers.stream() + .filter(item -> StringUtils.equals(item.getPluginId(), request.getPluginId())) + .findFirst() + .orElse(null); + if (pluginWrapper == null || !(pluginWrapper.getPlugin() instanceof AbstractApiPlugin)) { + // 插件不存在或者非接口插件,抛出异常 + ServiceUtils.checkResourceExist(null, "permission.api_plugin.name"); + } + ApiPluginOptionsRequest optionsRequest = BeanUtils.copyBean(new ApiPluginOptionsRequest(), request); + return ((AbstractApiPlugin) pluginWrapper.getPlugin()).getPluginOptions(optionsRequest); + } } \ No newline at end of file diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestControllerTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestControllerTests.java index a7ca763714..3f18ff9aa0 100644 --- a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestControllerTests.java +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestControllerTests.java @@ -1,21 +1,37 @@ package io.metersphere.api.controller; +import io.metersphere.api.dto.ApiTestPluginOptionRequest; import io.metersphere.api.service.BaseResourcePoolTestService; +import io.metersphere.plugin.api.dto.ApiPluginSelectOption; import io.metersphere.project.constants.ScriptLanguageType; import io.metersphere.project.dto.customfunction.request.CustomFunctionRunRequest; import io.metersphere.project.dto.environment.KeyValueParam; import io.metersphere.sdk.constants.PermissionConstants; +import io.metersphere.system.base.BasePluginTestService; import io.metersphere.system.base.BaseTest; +import io.metersphere.system.domain.Plugin; +import io.metersphere.system.dto.request.PluginUpdateRequest; +import io.metersphere.system.service.PluginService; import io.metersphere.system.uid.IDGenerator; import jakarta.annotation.Resource; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.web.servlet.MvcResult; +import java.io.File; +import java.io.FileInputStream; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import static io.metersphere.sdk.constants.InternalUserRole.ADMIN; +import static io.metersphere.system.controller.handler.result.MsHttpResultCode.NOT_FOUND; + /** * @Author: jianxing * @CreateTime: 2023-11-07 17:07 @@ -29,9 +45,14 @@ public class ApiTestControllerTests extends BaseTest { protected static final String PROTOCOL_LIST = "protocol/{0}"; protected static final String MOCK = "mock/{0}"; protected static final String CUSTOM_FUNC_RUN = "custom/func/run"; + protected static final String PLUGIN_FORM_OPTION = "plugin/form/option"; @Resource private BaseResourcePoolTestService baseResourcePoolTestService; + @Resource + private PluginService pluginService; + @Resource + private BasePluginTestService basePluginTestService; @Override protected String getBasePath() { return BASE_PATH; @@ -75,4 +96,50 @@ public class ApiTestControllerTests extends BaseTest { // @@校验权限 requestPostPermissionTest(PermissionConstants.PROJECT_CUSTOM_FUNCTION_EXECUTE, CUSTOM_FUNC_RUN, request); } + + @Test + public void getFormOptions() throws Exception { + ApiTestPluginOptionRequest request = new ApiTestPluginOptionRequest(); + request.setOrgId(DEFAULT_ORGANIZATION_ID); + request.setQueryParam(new HashMap<>()); + request.setPluginId("aaa"); + request.setOptionMethod("testGetApiPluginSelectOption"); + assertErrorCode(this.requestPost(PLUGIN_FORM_OPTION, request), NOT_FOUND); + Plugin jiraPlugin = basePluginTestService.addJiraPlugin(); + request.setPluginId(jiraPlugin.getId()); + assertErrorCode(this.requestPost(PLUGIN_FORM_OPTION, request), NOT_FOUND); + // @@请求成功 + Plugin plugin = addOptionTestPlugin(); + request.setPluginId(plugin.getId()); + MvcResult mvcResult = this.requestPostWithOkAndReturn(PLUGIN_FORM_OPTION, request); + List options = getResultDataArray(mvcResult, ApiPluginSelectOption.class); + Assertions.assertEquals(options.size(), 1); + + basePluginTestService.deleteJiraPlugin(); + pluginService.delete(plugin.getId()); + + // @@校验权限 + requestPostPermissionsTest(new ArrayList<>() {{ + add(PermissionConstants.PROJECT_API_DEFINITION_READ); + add(PermissionConstants.PROJECT_API_DEFINITION_CASE_READ); + add(PermissionConstants.PROJECT_API_DEBUG_READ); + add(PermissionConstants.PROJECT_API_SCENARIO_READ); + }}, PLUGIN_FORM_OPTION, request); + } + + public Plugin addOptionTestPlugin() throws Exception { + PluginUpdateRequest request = new PluginUpdateRequest(); + File jarFile = new File( + this.getClass().getClassLoader().getResource("file/dubbo-option-test-sampler-v3.x.jar") + .getPath() + ); + FileInputStream inputStream = new FileInputStream(jarFile); + MockMultipartFile mockMultipartFile = new MockMultipartFile(jarFile.getName(), jarFile.getName(), "jar", inputStream); + request.setName("测试获取选项插件"); + request.setGlobal(true); + request.setEnable(true); + request.setCreateUser(ADMIN.name()); + return pluginService.add(request, mockMultipartFile); + } + } diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestServiceTest.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestServiceTest.java index f957e55879..0b27beffb1 100644 --- a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestServiceTest.java +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestServiceTest.java @@ -40,6 +40,7 @@ public class ApiTestServiceTest extends BaseTest { httpProtocol.setPolymorphicName(MsHTTPElement.class.getSimpleName()); ProtocolDTO jdbcProtocol = new ProtocolDTO(); jdbcProtocol.setProtocol("JDBC"); + jdbcProtocol.setPluginId("jdbc"); jdbcProtocol.setPolymorphicName("MsJDBCElement"); expected.add(httpProtocol); expected.add(jdbcProtocol); diff --git a/backend/services/api-test/src/test/resources/file/dubbo-option-test-sampler-v3.x.jar b/backend/services/api-test/src/test/resources/file/dubbo-option-test-sampler-v3.x.jar new file mode 100644 index 0000000000000000000000000000000000000000..697b768acf7bca403b7b39d096cd42adbc174847 GIT binary patch literal 4297 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 Pf6kE0V_$MH008_Kz7S9g literal 0 HcmV?d00001 diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/dto/ProtocolDTO.java b/backend/services/system-setting/src/main/java/io/metersphere/system/dto/ProtocolDTO.java index 93c76585fd..6e398cf5db 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/dto/ProtocolDTO.java +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/dto/ProtocolDTO.java @@ -17,4 +17,8 @@ public class ProtocolDTO { * 例如 Http 对应 MsHTTPElement */ private String polymorphicName; + /** + * 插件ID + */ + private String pluginId; } diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/service/ApiPluginService.java b/backend/services/system-setting/src/main/java/io/metersphere/system/service/ApiPluginService.java index 8f278eee2b..56fc61554d 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/service/ApiPluginService.java +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/service/ApiPluginService.java @@ -1,5 +1,6 @@ package io.metersphere.system.service; +import io.metersphere.plugin.api.spi.AbstractApiPlugin; import io.metersphere.plugin.api.spi.AbstractProtocolPlugin; import io.metersphere.plugin.api.spi.MsTestElement; import io.metersphere.sdk.constants.PluginScenarioType; @@ -29,20 +30,12 @@ public class ApiPluginService { /** * 获取协议插件的的协议列表 + * * @param orgId * @return */ public List getProtocols(String orgId) { - // 查询组织下有权限的插件 - Set pluginIds = basePluginService.getOrgEnabledPlugins(orgId, PluginScenarioType.API_PROTOCOL) - .stream() - .map(Plugin::getId) - .collect(Collectors.toSet()); - - // 过滤协议插件 - List plugins = pluginLoadService.getMsPluginManager().getPlugins(); - List pluginWrappers = plugins.stream() - .filter(plugin -> pluginIds.contains(plugin.getPluginId()) && plugin.getPlugin() instanceof AbstractProtocolPlugin).toList(); + List pluginWrappers = getOrgProtocolPluginWrappers(orgId); List protocols = new ArrayList(); pluginWrappers.forEach(pluginWrapper -> { @@ -54,6 +47,7 @@ public class ApiPluginService { AbstractProtocolPlugin protocolPlugin = ((AbstractProtocolPlugin) pluginWrapper.getPlugin()); ProtocolDTO protocolDTO = new ProtocolDTO(); protocolDTO.setProtocol(protocolPlugin.getProtocol()); + protocolDTO.setPluginId(pluginWrapper.getPluginId()); if (CollectionUtils.isNotEmpty(extensionClasses)) { protocolDTO.setPolymorphicName(extensionClasses.get(0).getSimpleName()); } @@ -66,4 +60,25 @@ public class ApiPluginService { }); return protocols; } + + private List getOrgProtocolPluginWrappers(String orgId) { + return getOrgApiPluginWrappers(orgId).stream() + .filter(plugin -> plugin.getPlugin() instanceof AbstractProtocolPlugin) + .toList(); + } + + public List getOrgApiPluginWrappers(String orgId) { + // 查询组织下有权限的插件 + Set pluginIds = basePluginService.getOrgEnabledPlugins(orgId, PluginScenarioType.API_PROTOCOL) + .stream() + .map(Plugin::getId) + .collect(Collectors.toSet()); + + // 过滤协议插件 + List plugins = pluginLoadService.getMsPluginManager().getPlugins(); + List pluginWrappers = plugins.stream() + .filter(plugin -> pluginIds.contains(plugin.getPluginId()) && plugin.getPlugin() instanceof AbstractApiPlugin) + .toList(); + return pluginWrappers; + } } diff --git a/backend/services/system-setting/src/test/java/io/metersphere/system/service/ApiPluginServiceTests.java b/backend/services/system-setting/src/test/java/io/metersphere/system/service/ApiPluginServiceTests.java index 650c6d7139..95d7e3414e 100644 --- a/backend/services/system-setting/src/test/java/io/metersphere/system/service/ApiPluginServiceTests.java +++ b/backend/services/system-setting/src/test/java/io/metersphere/system/service/ApiPluginServiceTests.java @@ -37,6 +37,7 @@ public class ApiPluginServiceTests extends BaseTest { ProtocolDTO jdbcProtocol = new ProtocolDTO(); jdbcProtocol.setProtocol("JDBC"); jdbcProtocol.setPolymorphicName("MsJDBCElement"); + jdbcProtocol.setPluginId("jdbc"); expected.add(jdbcProtocol); Assertions.assertEquals(protocols, expected); }