添加 api 单元测试模板.

This commit is contained in:
lijiahang
2023-08-25 10:07:53 +08:00
parent 58901b5903
commit 4ec30b3933
12 changed files with 233 additions and 77 deletions

View File

@@ -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 <T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups) {
return Sets.empty();
}
@Override
public <T> Set<ConstraintViolation<T>> validateProperty(T object, String propertyName, Class<?>... groups) {
return Sets.empty();
}
@Override
public <T> Set<ConstraintViolation<T>> validateValue(Class<T> beanType, String propertyName, Object value, Class<?>... groups) {
return Sets.empty();
}
@Override
public BeanDescriptor getConstraintsForClass(Class<?> clazz) {
return null;
}
@Override
public <T> T unwrap(Class<T> type) {
return null;
}
@Override
public ExecutableValidator forExecutables() {
return null;
}
};
}
}

View File

@@ -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();
}
};
}
}

View File

@@ -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,

View File

@@ -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"},
// -------------------- 前端 --------------------

View File

@@ -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");
}
/**
* 是否为后端单元测试文件
*

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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}}
###

View File

@@ -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}}
###

View File

@@ -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<SystemRoleVO> getSystemRolePage(@Validated @RequestBody SystemRoleQueryRequest request) {
public DataGrid<SystemRoleVO> getSystemRolePage(@Validated(IPageRequest.class) @RequestBody SystemRoleQueryRequest request) {
return systemRoleService.getSystemRolePage(request);
}

View File

@@ -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}}
###

View File

@@ -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<SystemUserVO> getSystemUserPage(@Validated @RequestBody SystemUserQueryRequest request) {
public DataGrid<SystemUserVO> getSystemUserPage(@Validated(IPageRequest.class) @RequestBody SystemUserQueryRequest request) {
return systemUserService.getSystemUserPage(request);
}