diff --git a/orion-ops-framework/orion-ops-spring-boot-starter-test/src/main/java/com/orion/ops/framework/test/config/OrionMockBeanTestConfiguration.java b/orion-ops-framework/orion-ops-spring-boot-starter-test/src/main/java/com/orion/ops/framework/test/config/OrionMockBeanTestConfiguration.java new file mode 100644 index 00000000..3621127b --- /dev/null +++ b/orion-ops-framework/orion-ops-spring-boot-starter-test/src/main/java/com/orion/ops/framework/test/config/OrionMockBeanTestConfiguration.java @@ -0,0 +1,96 @@ +package com.orion.ops.framework.test.config; + +import com.orion.lang.utils.collect.Sets; +import com.orion.ops.framework.common.security.LoginUser; +import com.orion.ops.framework.common.security.SecurityHolder; +import com.orion.ops.framework.test.core.utils.EntityRandoms; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Lazy; +import org.springframework.context.annotation.Profile; + +import javax.validation.ConstraintViolation; +import javax.validation.Validator; +import javax.validation.executable.ExecutableValidator; +import javax.validation.metadata.BeanDescriptor; +import java.util.Set; + +/** + * 单元测试依赖 bean 初始化 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2023/8/24 14:53 + */ +@Lazy(false) +@Profile("unit-test") +@Configuration(proxyBeanMethods = false) +public class OrionMockBeanTestConfiguration { + + /** + * 空实现数据填充器 用于单元测试 单元测试不会注入 spring-security + * + * @return SecurityHolder + */ + @Bean + @ConditionalOnMissingBean(SecurityHolder.class) + public SecurityHolder emptySecurityHolder() { + return new SecurityHolder() { + + private final LoginUser DEFAULT = EntityRandoms.random(LoginUser.class); + + @Override + public LoginUser getLoginUser() { + return DEFAULT; + } + + @Override + public Long getLoginUserId() { + return DEFAULT.getId(); + } + }; + } + + /** + * 空实现对象验证器 用于单元测试 + * + * @return Validator + */ + @Bean + @ConditionalOnMissingBean(Validator.class) + public Validator emptyValidator() { + return new Validator() { + @Override + public Set> validate(T object, Class... groups) { + return Sets.empty(); + } + + @Override + public Set> validateProperty(T object, String propertyName, Class... groups) { + return Sets.empty(); + } + + @Override + public Set> validateValue(Class beanType, String propertyName, Object value, Class... groups) { + return Sets.empty(); + } + + @Override + public BeanDescriptor getConstraintsForClass(Class clazz) { + return null; + } + + @Override + public T unwrap(Class type) { + return null; + } + + @Override + public ExecutableValidator forExecutables() { + return null; + } + }; + } + +} diff --git a/orion-ops-framework/orion-ops-spring-boot-starter-test/src/main/java/com/orion/ops/framework/test/config/OrionSecurityTestConfiguration.java b/orion-ops-framework/orion-ops-spring-boot-starter-test/src/main/java/com/orion/ops/framework/test/config/OrionSecurityTestConfiguration.java deleted file mode 100644 index c339d305..00000000 --- a/orion-ops-framework/orion-ops-spring-boot-starter-test/src/main/java/com/orion/ops/framework/test/config/OrionSecurityTestConfiguration.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.orion.ops.framework.test.config; - -import com.orion.ops.framework.common.security.LoginUser; -import com.orion.ops.framework.common.security.SecurityHolder; -import com.orion.ops.framework.test.core.utils.EntityRandoms; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Lazy; -import org.springframework.context.annotation.Profile; - -/** - * 单元测试 security 初始化 - * - * @author Jiahang Li - * @version 1.0.0 - * @since 2023/8/24 14:53 - */ -@Lazy(false) -@Profile("unit-test") -@Configuration(proxyBeanMethods = false) -public class OrionSecurityTestConfiguration { - - /** - * 空实现数据填充器 用于单元测试 单元测试不会注入 spring-security - * - * @return SecurityHolder - */ - @Bean - @Profile("unit-test") - @ConditionalOnMissingBean(SecurityHolder.class) - public SecurityHolder emptySecurityHolder() { - return new SecurityHolder() { - - private final LoginUser DEFAULT = EntityRandoms.random(LoginUser.class); - - @Override - public LoginUser getLoginUser() { - return DEFAULT; - } - - @Override - public Long getLoginUserId() { - return DEFAULT.getId(); - } - }; - } - -} diff --git a/orion-ops-framework/orion-ops-spring-boot-starter-test/src/main/java/com/orion/ops/framework/test/core/base/BaseUnitTest.java b/orion-ops-framework/orion-ops-spring-boot-starter-test/src/main/java/com/orion/ops/framework/test/core/base/BaseUnitTest.java index 38782947..6ef1d578 100644 --- a/orion-ops-framework/orion-ops-spring-boot-starter-test/src/main/java/com/orion/ops/framework/test/core/base/BaseUnitTest.java +++ b/orion-ops-framework/orion-ops-spring-boot-starter-test/src/main/java/com/orion/ops/framework/test/core/base/BaseUnitTest.java @@ -2,12 +2,13 @@ package com.orion.ops.framework.test.core.base; import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure; import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; +import com.orion.ops.framework.common.config.OrionCommonAutoConfiguration; import com.orion.ops.framework.datasource.config.OrionDataSourceAutoConfiguration; import com.orion.ops.framework.mybatis.config.OrionMybatisAutoConfiguration; import com.orion.ops.framework.redis.config.OrionRedisAutoConfiguration; import com.orion.ops.framework.test.config.OrionH2SqlInitializationTestConfiguration; +import com.orion.ops.framework.test.config.OrionMockBeanTestConfiguration; import com.orion.ops.framework.test.config.OrionMockRedisTestConfiguration; -import com.orion.ops.framework.test.config.OrionSecurityTestConfiguration; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.TestMethodOrder; import org.redisson.spring.starter.RedissonAutoConfiguration; @@ -35,8 +36,10 @@ import org.springframework.transaction.annotation.Transactional; public class BaseUnitTest { @Import({ - // security - OrionSecurityTestConfiguration.class, + // holder + OrionCommonAutoConfiguration.class, + // mock + OrionMockBeanTestConfiguration.class, // datasource OrionDataSourceAutoConfiguration.class, DruidDataSourceAutoConfigure.class, diff --git a/orion-ops-launch/src/main/java/com/orion/ops/launch/generator/CodeGenerator.java b/orion-ops-launch/src/main/java/com/orion/ops/launch/generator/CodeGenerator.java index 30686fb0..17f06b91 100644 --- a/orion-ops-launch/src/main/java/com/orion/ops/launch/generator/CodeGenerator.java +++ b/orion-ops-launch/src/main/java/com/orion/ops/launch/generator/CodeGenerator.java @@ -319,8 +319,10 @@ public class CodeGenerator { // convert 文件 new String[]{"/templates/orion-server-provider-convert.java.vm", "${type}ProviderConvert.java", "convert"}, // -------------------- 后端 - test -------------------- - // unit test 文件 - new String[]{"/templates/orion-server-test-service-tests.java.vm", "${type}ServiceTests.java", "service.impl"}, + // service unit test 文件 + new String[]{"/templates/orion-server-test-service-impl-tests.java.vm", "${type}ServiceImplTests.java", "service.impl"}, + // api unit test 文件 + new String[]{"/templates/orion-server-test-api-impl-tests.java.vm", "${type}ApiImplTests.java", "api.impl"}, // create table sql 文件 new String[]{"/templates/orion-server-test-create-table.sql.vm", "create-table-h2-${tableName}.sql", "sql"}, // -------------------- 前端 -------------------- diff --git a/orion-ops-launch/src/main/java/com/orion/ops/launch/generator/VelocityTemplateEngine.java b/orion-ops-launch/src/main/java/com/orion/ops/launch/generator/VelocityTemplateEngine.java index 8708bb10..d20d388f 100644 --- a/orion-ops-launch/src/main/java/com/orion/ops/launch/generator/VelocityTemplateEngine.java +++ b/orion-ops-launch/src/main/java/com/orion/ops/launch/generator/VelocityTemplateEngine.java @@ -148,6 +148,10 @@ public class VelocityTemplateEngine extends AbstractTemplateEngine { // 不生成对外 api 文件 if (!table.isGenProviderApi()) { files.removeIf(file -> this.isServerProviderFile(file.getTemplatePath())); + // 不生成对外 api 单元测试文件 + if (table.isGenUnitTest()) { + files.removeIf(file -> this.isServerProviderTestFile(file.getTemplatePath())); + } } // 不生成单元测试文件 if (!table.isGenUnitTest()) { @@ -343,6 +347,16 @@ public class VelocityTemplateEngine extends AbstractTemplateEngine { return templatePath.contains("orion-server-provider"); } + /** + * 是否为后端 provider 单元测试文件 + * + * @param templatePath templatePath + * @return 是否为后端 provider 单元测试文件 + */ + private boolean isServerProviderTestFile(String templatePath) { + return templatePath.contains("orion-server-test-api"); + } + /** * 是否为后端单元测试文件 * diff --git a/orion-ops-launch/src/main/resources/templates/orion-server-test-api-impl-tests.java.vm b/orion-ops-launch/src/main/resources/templates/orion-server-test-api-impl-tests.java.vm new file mode 100644 index 00000000..bb68dd34 --- /dev/null +++ b/orion-ops-launch/src/main/resources/templates/orion-server-test-api-impl-tests.java.vm @@ -0,0 +1,96 @@ +package ${currentPackage}; + +import com.orion.lang.define.wrapper.DataGrid; +import com.orion.lang.utils.collect.Lists; +import com.orion.ops.framework.test.core.base.BaseUnitTest; +import com.orion.ops.framework.test.core.utils.EntityRandoms; +import ${package.ServiceImpl}.*; +#foreach($pkg in ${customProviderFilePackages}) +import ${pkg}.*; +#end +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * $!{table.comment} 对外服务单元测试 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2023/8/23 10:36 + */ +@Slf4j +@Import({${type}ApiImpl.class, ${type}ServiceImpl.class}) +public class ${type}ApiImplTests extends BaseUnitTest { + + @Resource + private ${type}Api ${typeLower}Api; + + private static Long lastId; + + @Test + @Order(1) + public void create${type}Test() { + ${type}CreateDTO req = EntityRandoms.random(${type}CreateDTO.class); + lastId = ${typeLower}Api.create${type}(req); + assertNotNull(lastId); + } + + @Test + @Order(2) + public void update${type}ByIdTest() { + ${type}UpdateDTO req = EntityRandoms.random(${type}UpdateDTO.class); + req.setId(lastId); + Integer effect = ${typeLower}Api.update${type}ById(req); + assertEquals(effect, 1); + } + + @Test + @Order(3) + public void get${type}ByIdTest() { + ${type}DTO row = ${typeLower}Api.get${type}ById(lastId); + assertNotNull(row); + } + + @Test + @Order(4) + public void get${type}ByIdListTest() { + List<${type}DTO> rows = ${typeLower}Api.get${type}ByIdList(Lists.of(lastId)); + assertFalse(rows.isEmpty()); + } + + @Test + @Order(5) + public void get${type}ListTest() { + List<${type}DTO> rows = ${typeLower}Api.get${type}List(new ${type}QueryDTO()); + assertFalse(rows.isEmpty()); + } + + @Test + @Order(6) + public void get${type}CountTest() { + Long count = ${typeLower}Api.get${type}Count(new ${type}QueryDTO()); + assertEquals(count, 1L); + } + + @Test + @Order(7) + public void delete${type}ByIdTest() { + Integer effect = ${typeLower}Api.delete${type}ById(lastId); + assertEquals(effect, 1); + } + + @Test + @Order(8) + public void batchDelete${type}ByIdListTest() { + Integer effect = ${typeLower}Api.batchDelete${type}ByIdList(Lists.of(lastId)); + assertEquals(effect, 0); + } + +} diff --git a/orion-ops-launch/src/main/resources/templates/orion-server-test-service-tests.java.vm b/orion-ops-launch/src/main/resources/templates/orion-server-test-service-impl-tests.java.vm similarity index 96% rename from orion-ops-launch/src/main/resources/templates/orion-server-test-service-tests.java.vm rename to orion-ops-launch/src/main/resources/templates/orion-server-test-service-impl-tests.java.vm index 7ac990cf..80787bae 100644 --- a/orion-ops-launch/src/main/resources/templates/orion-server-test-service-tests.java.vm +++ b/orion-ops-launch/src/main/resources/templates/orion-server-test-service-impl-tests.java.vm @@ -4,6 +4,7 @@ import com.orion.lang.define.wrapper.DataGrid; import com.orion.lang.utils.collect.Lists; import com.orion.ops.framework.test.core.base.BaseUnitTest; import com.orion.ops.framework.test.core.utils.EntityRandoms; +import ${package.Service}.*; #foreach($pkg in ${customModuleFilePackages}) import ${pkg}.*; #end @@ -26,7 +27,7 @@ import static org.junit.jupiter.api.Assertions.*; */ @Slf4j @Import(${type}ServiceImpl.class) -public class ${type}ServiceTests extends BaseUnitTest { +public class ${type}ServiceImplTests extends BaseUnitTest { @Resource private ${type}Service ${typeLower}Service; diff --git a/orion-ops-module-infra/orion-ops-module-infra-service/src/main/java/com/orion/ops/module/infra/controller/SystemMenuController.http b/orion-ops-module-infra/orion-ops-module-infra-service/src/main/java/com/orion/ops/module/infra/controller/SystemMenuController.http index 00bf3568..689197b9 100644 --- a/orion-ops-module-infra/orion-ops-module-infra-service/src/main/java/com/orion/ops/module/infra/controller/SystemMenuController.http +++ b/orion-ops-module-infra/orion-ops-module-infra-service/src/main/java/com/orion/ops/module/infra/controller/SystemMenuController.http @@ -47,27 +47,9 @@ GET {{baseUrl}}/infra/system-menu/list?idList=1,2,3 Authorization: {{token}} -### 分页查询菜单 -POST {{baseUrl}}/infra/system-menu/query -Content-Type: application/json -Authorization: {{token}} - -{ - "id": "", - "parentId": "", - "name": "", - "permission": "", - "type": "", - "sort": "", - "status": "", - "cache": "", - "icon": "", - "path": "", - "component": "" -} - - ### 通过 id 删除菜单 DELETE {{baseUrl}}/infra/system-menu/delete?id=1 Authorization: {{token}} + +### diff --git a/orion-ops-module-infra/orion-ops-module-infra-service/src/main/java/com/orion/ops/module/infra/controller/SystemRoleController.http b/orion-ops-module-infra/orion-ops-module-infra-service/src/main/java/com/orion/ops/module/infra/controller/SystemRoleController.http index 78099ded..3035f8e6 100644 --- a/orion-ops-module-infra/orion-ops-module-infra-service/src/main/java/com/orion/ops/module/infra/controller/SystemRoleController.http +++ b/orion-ops-module-infra/orion-ops-module-infra-service/src/main/java/com/orion/ops/module/infra/controller/SystemRoleController.http @@ -50,6 +50,8 @@ Content-Type: application/json Authorization: {{token}} { + "page": 1, + "limit": 10, "id": "", "name": "", "code": "", @@ -60,3 +62,6 @@ Authorization: {{token}} ### 通过 id 删除角色 DELETE {{baseUrl}}/infra/system-role/delete?id=1 Authorization: {{token}} + + +### diff --git a/orion-ops-module-infra/orion-ops-module-infra-service/src/main/java/com/orion/ops/module/infra/controller/SystemRoleController.java b/orion-ops-module-infra/orion-ops-module-infra-service/src/main/java/com/orion/ops/module/infra/controller/SystemRoleController.java index 5225adec..5f4d6ab5 100644 --- a/orion-ops-module-infra/orion-ops-module-infra-service/src/main/java/com/orion/ops/module/infra/controller/SystemRoleController.java +++ b/orion-ops-module-infra/orion-ops-module-infra-service/src/main/java/com/orion/ops/module/infra/controller/SystemRoleController.java @@ -1,6 +1,7 @@ package com.orion.ops.module.infra.controller; import com.orion.lang.define.wrapper.DataGrid; +import com.orion.lang.define.wrapper.IPageRequest; import com.orion.ops.framework.common.annotation.IgnoreLog; import com.orion.ops.framework.common.annotation.RestWrapper; import com.orion.ops.framework.common.constant.IgnoreLogMode; @@ -87,7 +88,7 @@ public class SystemRoleController { @PostMapping("/query") @Operation(summary = "分页查询角色") @PreAuthorize("@ss.hasPermission('infra:system-role:query')") - public DataGrid getSystemRolePage(@Validated @RequestBody SystemRoleQueryRequest request) { + public DataGrid getSystemRolePage(@Validated(IPageRequest.class) @RequestBody SystemRoleQueryRequest request) { return systemRoleService.getSystemRolePage(request); } diff --git a/orion-ops-module-infra/orion-ops-module-infra-service/src/main/java/com/orion/ops/module/infra/controller/SystemUserController.http b/orion-ops-module-infra/orion-ops-module-infra-service/src/main/java/com/orion/ops/module/infra/controller/SystemUserController.http index 78fa2c71..c645b381 100644 --- a/orion-ops-module-infra/orion-ops-module-infra-service/src/main/java/com/orion/ops/module/infra/controller/SystemUserController.http +++ b/orion-ops-module-infra/orion-ops-module-infra-service/src/main/java/com/orion/ops/module/infra/controller/SystemUserController.http @@ -49,6 +49,8 @@ Content-Type: application/json Authorization: {{token}} { + "page": 1, + "limit": 10, "id": "", "username": "", "password": "", @@ -65,3 +67,5 @@ Authorization: {{token}} DELETE {{baseUrl}}/infra/system-user/delete?id=1 Authorization: {{token}} + +### diff --git a/orion-ops-module-infra/orion-ops-module-infra-service/src/main/java/com/orion/ops/module/infra/controller/SystemUserController.java b/orion-ops-module-infra/orion-ops-module-infra-service/src/main/java/com/orion/ops/module/infra/controller/SystemUserController.java index c775a2df..05ce3a08 100644 --- a/orion-ops-module-infra/orion-ops-module-infra-service/src/main/java/com/orion/ops/module/infra/controller/SystemUserController.java +++ b/orion-ops-module-infra/orion-ops-module-infra-service/src/main/java/com/orion/ops/module/infra/controller/SystemUserController.java @@ -2,6 +2,7 @@ package com.orion.ops.module.infra.controller; import com.orion.lang.define.wrapper.DataGrid; import com.orion.lang.define.wrapper.HttpWrapper; +import com.orion.lang.define.wrapper.IPageRequest; import com.orion.lang.utils.collect.Lists; import com.orion.ops.framework.common.annotation.IgnoreLog; import com.orion.ops.framework.common.annotation.RestWrapper; @@ -116,7 +117,7 @@ public class SystemUserController { @PostMapping("/query") @Operation(summary = "分页查询用户") @PreAuthorize("@ss.hasPermission('infra:system-user:query')") - public DataGrid getSystemUserPage(@Validated @RequestBody SystemUserQueryRequest request) { + public DataGrid getSystemUserPage(@Validated(IPageRequest.class) @RequestBody SystemUserQueryRequest request) { return systemUserService.getSystemUserPage(request); }