Merge branch '20260204'

# Conflicts:
#	.idea/compiler.xml
#	.idea/vcs.xml
#	lidee-admin/src/main/resources/application-local.yaml
#	lidee-admin/target/classes/application-local.yaml
#	lidee-admin/target/lidee-admin.jar
#	lidee-admin/target/lidee-admin.jar.original
#	lidee-admin/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
#	lidee-core/src/main/java/com/lideeyunji/core/framework/entity/ReportFieldEntity.java
#	lidee-core/src/main/java/com/lideeyunji/core/framework/service/impl/ReportServiceImpl.java
#	lidee-core/target/classes/com/lideeyunji/core/framework/entity/ReportFieldEntity.class
#	lidee-core/target/classes/com/lideeyunji/core/framework/service/impl/ReportServiceImpl.class
#	lidee-core/target/lidee-core-2.2.4.jar
#	lidee-core/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
#	lidee-module/lidee-module-api/target/lidee-module-api-2.2.4.jar
#	lidee-module/lidee-module-api/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
#	lidee-module/lidee-module-biz/target/lidee-module-biz-2.2.4.jar
#	lidee-module/lidee-module-biz/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
#	lidee-service/lidee-service-infra-api/target/lidee-service-infra-api-2.2.4.jar
#	lidee-service/lidee-service-infra-biz/target/lidee-service-infra-biz-2.2.4.jar
#	lidee-service/lidee-service-system-api/target/lidee-service-system-api-2.2.4.jar
#	lidee-service/lidee-service-system-biz/target/lidee-service-system-biz-2.2.4.jar
#	lidee-tool/tool-common/target/tool-common-2.2.4.jar
#	lidee-tool/tool-spring-boot-starter-ai/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
#	lidee-tool/tool-spring-boot-starter-ai/target/tool-spring-boot-starter-ai-2.2.4.jar
#	lidee-tool/tool-spring-boot-starter-captcha/target/tool-spring-boot-starter-captcha-2.2.4.jar
#	lidee-tool/tool-spring-boot-starter-dict/target/tool-spring-boot-starter-dict-2.2.4.jar
#	lidee-tool/tool-spring-boot-starter-excel/target/tool-spring-boot-starter-excel-2.2.4.jar
#	lidee-tool/tool-spring-boot-starter-exception/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
#	lidee-tool/tool-spring-boot-starter-exception/target/tool-spring-boot-starter-exception-2.2.4.jar
#	lidee-tool/tool-spring-boot-starter-file/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
#	lidee-tool/tool-spring-boot-starter-file/target/tool-spring-boot-starter-file-2.2.4.jar
#	lidee-tool/tool-spring-boot-starter-flowable/target/tool-spring-boot-starter-flowable-2.2.4.jar
#	lidee-tool/tool-spring-boot-starter-ip/target/tool-spring-boot-starter-ip-2.2.4.jar
#	lidee-tool/tool-spring-boot-starter-job/target/tool-spring-boot-starter-job-2.2.4.jar
#	lidee-tool/tool-spring-boot-starter-monitor/target/tool-spring-boot-starter-monitor-2.2.4.jar
#	lidee-tool/tool-spring-boot-starter-mybatis/target/tool-spring-boot-starter-mybatis-2.2.4.jar
#	lidee-tool/tool-spring-boot-starter-operatelog/target/tool-spring-boot-starter-operatelog-2.2.4.jar
#	lidee-tool/tool-spring-boot-starter-permission/target/tool-spring-boot-starter-permission-2.2.4.jar
#	lidee-tool/tool-spring-boot-starter-protection/target/tool-spring-boot-starter-protection-2.2.4.jar
#	lidee-tool/tool-spring-boot-starter-redis/target/tool-spring-boot-starter-redis-2.2.4.jar
#	lidee-tool/tool-spring-boot-starter-security/target/tool-spring-boot-starter-security-2.2.4.jar
#	lidee-tool/tool-spring-boot-starter-sql/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
#	lidee-tool/tool-spring-boot-starter-sql/target/tool-spring-boot-starter-sql-2.2.4.jar
#	lidee-tool/tool-spring-boot-starter-tenant/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
#	lidee-tool/tool-spring-boot-starter-tenant/target/tool-spring-boot-starter-tenant-2.2.4.jar
#	lidee-tool/tool-spring-boot-starter-test/target/tool-spring-boot-starter-test-2.2.4.jar
#	lidee-tool/tool-spring-boot-starter-web/target/tool-spring-boot-starter-web-2.2.4.jar
#	lidee-tool/tool-spring-boot-starter-websocket/target/tool-spring-boot-starter-websocket-2.2.4.jar
#	lidee-tool/tool-spring-boot-starter-yunji/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
#	lidee-tool/tool-spring-boot-starter-yunji/target/tool-spring-boot-starter-yunji-2.2.4.jar
#	logs/lideeyunji-error.log
#	logs/lideeyunji-info.log
This commit is contained in:
chy
2026-02-09 23:30:06 +08:00
1718 changed files with 66 additions and 116884 deletions

View File

@@ -1,49 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.lideeyunji</groupId>
<artifactId>lidee-tool</artifactId>
<version>2.2.4</version>
</parent>
<groupId>com.lideeyunji</groupId>
<artifactId>tool-spring-boot-starter-test</artifactId>
<version>2.2.4</version>
<name>${project.artifactId}</name>
<description>测试组件,用于单元测试、集成测试</description>
<dependencies>
<dependency>
<groupId>com.lideeyunji</groupId>
<artifactId>tool-common</artifactId>
</dependency>
<dependency>
<groupId>com.lideeyunji</groupId>
<artifactId>tool-spring-boot-starter-mybatis</artifactId>
</dependency>
<dependency>
<groupId>com.lideeyunji</groupId>
<artifactId>tool-spring-boot-starter-redis</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>com.github.fppt</groupId>
<artifactId>jedis-mock</artifactId>
</dependency>
<dependency>
<groupId>uk.co.jemos.podam</groupId>
<artifactId>podam</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -1,60 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.lideeyunji</groupId>
<artifactId>lidee-tool</artifactId>
<version>${lidee.version}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>tool-spring-boot-starter-test</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>测试组件,用于单元测试、集成测试</description>
<dependencies>
<dependency>
<groupId>com.lideeyunji</groupId>
<artifactId>tool-common</artifactId>
</dependency>
<!-- DB 相关 -->
<dependency>
<groupId>com.lideeyunji</groupId>
<artifactId>tool-spring-boot-starter-mybatis</artifactId>
</dependency>
<dependency>
<groupId>com.lideeyunji</groupId>
<artifactId>tool-spring-boot-starter-redis</artifactId>
</dependency>
<!-- Test 测试相关 -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId> <!-- 单元测试,我们采用 H2 作为数据库 -->
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>com.github.fppt</groupId> <!-- 单元测试,我们采用内嵌的 Redis 数据库 -->
<artifactId>jedis-mock</artifactId>
</dependency>
<dependency>
<groupId>uk.co.jemos.podam</groupId> <!-- 单元测试,随机生成 POJO 类 -->
<artifactId>podam</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -1,35 +0,0 @@
package com.lideeyunji.tool.framework.test.config;
import com.github.fppt.jedismock.RedisServer;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import java.io.IOException;
/**
* Redis 测试 Configuration主要实现内嵌 Redis 的启动
*
* @author 金灯剑客
*/
@Configuration(proxyBeanMethods = false)
@Lazy(false) // 禁止延迟加载
@EnableConfigurationProperties(RedisProperties.class)
public class RedisTestConfiguration {
/**
* 创建模拟的 Redis Server 服务器
*/
@Bean
public RedisServer redisServer(RedisProperties properties) throws IOException {
RedisServer redisServer = new RedisServer(properties.getPort());
// 一次执行多个单元测试时,貌似创建多个 spring 容器,导致不进行 stop。这样就导致端口被占用无法启动。。。
try {
redisServer.start();
} catch (Exception ignore) {}
return redisServer;
}
}

View File

@@ -1,52 +0,0 @@
package com.lideeyunji.tool.framework.test.config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.autoconfigure.sql.init.SqlInitializationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer;
import org.springframework.boot.sql.init.AbstractScriptDatabaseInitializer;
import org.springframework.boot.sql.init.DatabaseInitializationSettings;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import javax.sql.DataSource;
/**
* SQL 初始化的测试 Configuration
*
* 为什么不使用 org.springframework.boot.autoconfigure.sql.init.DataSourceInitializationConfiguration 呢?
* 因为我们在单元测试会使用 spring.main.lazy-initialization 为 true开启延迟加载。此时会导致 DataSourceInitializationConfiguration 初始化
* 不过呢,当前类的实现代码,基本是复制 DataSourceInitializationConfiguration 的哈!
*
* @author 金灯剑客
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(AbstractScriptDatabaseInitializer.class)
@ConditionalOnSingleCandidate(DataSource.class)
@ConditionalOnClass(name = "org.springframework.jdbc.datasource.init.DatabasePopulator")
@Lazy(value = false) // 禁止延迟加载
@EnableConfigurationProperties(SqlInitializationProperties.class)
public class SqlInitializationTestConfiguration {
@Bean
public DataSourceScriptDatabaseInitializer dataSourceScriptDatabaseInitializer(DataSource dataSource,
SqlInitializationProperties initializationProperties) {
DatabaseInitializationSettings settings = createFrom(initializationProperties);
return new DataSourceScriptDatabaseInitializer(dataSource, settings);
}
static DatabaseInitializationSettings createFrom(SqlInitializationProperties properties) {
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
settings.setSchemaLocations(properties.getSchemaLocations());
settings.setDataLocations(properties.getDataLocations());
settings.setContinueOnError(properties.isContinueOnError());
settings.setSeparator(properties.getSeparator());
settings.setEncoding(properties.getEncoding());
settings.setMode(properties.getMode());
return settings;
}
}

View File

@@ -1,49 +0,0 @@
package com.lideeyunji.tool.framework.test.core.ut;
import com.lideeyunji.tool.framework.datasource.config.DataSourceAutoConfiguration;
import com.lideeyunji.tool.framework.mybatis.config.MybatisAutoConfiguration;
import com.lideeyunji.tool.framework.redis.config.RedisAutoConfiguration;
import com.lideeyunji.tool.framework.test.config.RedisTestConfiguration;
import com.lideeyunji.tool.framework.test.config.SqlInitializationTestConfiguration;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
import org.redisson.spring.starter.RedissonAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.jdbc.Sql;
/**
* 依赖内存 DB + Redis 的单元测试
*
* 相比 {@link BaseDbUnitTest} 来说,额外增加了内存 Redis
*
* @author 金灯剑客
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbAndRedisUnitTest.Application.class)
@ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件
@Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) // 每个单元测试结束后,清理 DB
public class BaseDbAndRedisUnitTest {
@Import({
// DB 配置类
DataSourceAutoConfiguration.class, // 自己的 DB 配置类
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration.class, // Spring DB 自动配置类
DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类
DruidDataSourceAutoConfigure.class, // Druid 自动配置类
SqlInitializationTestConfiguration.class, // SQL 初始化
// MyBatis 配置类
MybatisAutoConfiguration.class, // 自己的 MyBatis 配置类
MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类
// Redis 配置类
RedisTestConfiguration.class, // Redis 测试配置类,用于启动 RedisServer
RedisAutoConfiguration.class, // 自己的 Redis 配置类
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration.class, // Spring Redis 自动配置类
RedissonAutoConfiguration.class, // Redisson 自动高配置类
})
public static class Application {
}
}

View File

@@ -1,42 +0,0 @@
package com.lideeyunji.tool.framework.test.core.ut;
import com.lideeyunji.tool.framework.datasource.config.DataSourceAutoConfiguration;
import com.lideeyunji.tool.framework.mybatis.config.MybatisAutoConfiguration;
import com.lideeyunji.tool.framework.test.config.SqlInitializationTestConfiguration;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
import com.github.yulichang.autoconfigure.MybatisPlusJoinAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.jdbc.Sql;
/**
* 依赖内存 DB 的单元测试
*
* 注意Service 层同样适用。对于 Service 层的单元测试,我们针对自己模块的 Mapper 走的是 H2 内存数据库,针对别的模块的 Service 走的是 Mock 方法
*
* @author 金灯剑客
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbUnitTest.Application.class)
@ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件
@Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) // 每个单元测试结束后,清理 DB
public class BaseDbUnitTest {
@Import({
// DB 配置类
DataSourceAutoConfiguration.class, // 自己的 DB 配置类
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration.class, // Spring DB 自动配置类
DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类
DruidDataSourceAutoConfigure.class, // Druid 自动配置类
SqlInitializationTestConfiguration.class, // SQL 初始化
// MyBatis 配置类
MybatisAutoConfiguration.class, // 自己的 MyBatis 配置类
MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类
MybatisPlusJoinAutoConfiguration.class, // MyBatis 的Join配置类
})
public static class Application {
}
}

View File

@@ -1,13 +0,0 @@
package com.lideeyunji.tool.framework.test.core.ut;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
/**
* 纯 Mockito 的单元测试
*
* @author 金灯剑客
*/
@ExtendWith(MockitoExtension.class)
public class BaseMockitoUnitTest {
}

View File

@@ -1,31 +0,0 @@
package com.lideeyunji.tool.framework.test.core.ut;
import com.lideeyunji.tool.framework.redis.config.RedisAutoConfiguration;
import com.lideeyunji.tool.framework.test.config.RedisTestConfiguration;
import org.redisson.spring.starter.RedissonAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.ActiveProfiles;
/**
* 依赖内存 Redis 的单元测试
*
* 相比 {@link BaseDbUnitTest} 来说,从内存 DB 改成了内存 Redis
*
* @author 金灯剑客
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseRedisUnitTest.Application.class)
@ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件
public class BaseRedisUnitTest {
@Import({
// Redis 配置类
RedisTestConfiguration.class, // Redis 测试配置类,用于启动 RedisServer
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration.class, // Spring Redis 自动配置类
RedisAutoConfiguration.class, // 自己的 Redis 配置类
RedissonAutoConfiguration.class, // Redisson 自动高配置类
})
public static class Application {
}
}

View File

@@ -1,4 +0,0 @@
/**
* 提供单元测试 Unit Test 的基类
*/
package com.lideeyunji.tool.framework.test.core.ut;

View File

@@ -1,101 +0,0 @@
package com.lideeyunji.tool.framework.test.core.util;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ReflectUtil;
import com.lideeyunji.tool.framework.common.exception.ErrorCode;
import com.lideeyunji.tool.framework.common.exception.ServiceException;
import com.lideeyunji.tool.framework.common.exception.util.ServiceExceptionUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.function.Executable;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Objects;
import static org.junit.jupiter.api.Assertions.assertThrows;
/**
* 单元测试assert 断言工具类
*
* @author 金灯剑客
*/
public class AssertUtils {
/**
* 比对两个对象的属性是否一致
*
* 注意,如果 expected 存在的属性actual 不存在的时候,会进行忽略
*
* @param expected 期望对象
* @param actual 实际对象
* @param ignoreFields 忽略的属性数组
*/
public static void assertPojoEquals(Object expected, Object actual, String... ignoreFields) {
Field[] expectedFields = ReflectUtil.getFields(expected.getClass());
Arrays.stream(expectedFields).forEach(expectedField -> {
// 忽略 jacoco 自动生成的 $jacocoData 属性的情况
if (expectedField.isSynthetic()) {
return;
}
// 如果是忽略的属性,则不进行比对
if (ArrayUtil.contains(ignoreFields, expectedField.getName())) {
return;
}
// 忽略不存在的属性
Field actualField = ReflectUtil.getField(actual.getClass(), expectedField.getName());
if (actualField == null) {
return;
}
// 比对
Assertions.assertEquals(
ReflectUtil.getFieldValue(expected, expectedField),
ReflectUtil.getFieldValue(actual, actualField),
String.format("Field(%s) 不匹配", expectedField.getName())
);
});
}
/**
* 比对两个对象的属性是否一致
*
* 注意,如果 expected 存在的属性actual 不存在的时候,会进行忽略
*
* @param expected 期望对象
* @param actual 实际对象
* @param ignoreFields 忽略的属性数组
* @return 是否一致
*/
public static boolean isPojoEquals(Object expected, Object actual, String... ignoreFields) {
Field[] expectedFields = ReflectUtil.getFields(expected.getClass());
return Arrays.stream(expectedFields).allMatch(expectedField -> {
// 如果是忽略的属性,则不进行比对
if (ArrayUtil.contains(ignoreFields, expectedField.getName())) {
return true;
}
// 忽略不存在的属性
Field actualField = ReflectUtil.getField(actual.getClass(), expectedField.getName());
if (actualField == null) {
return true;
}
return Objects.equals(ReflectUtil.getFieldValue(expected, expectedField),
ReflectUtil.getFieldValue(actual, actualField));
});
}
/**
* 执行方法,校验抛出的 Service 是否符合条件
*
* @param executable 业务异常
* @param errorCode 错误码对象
* @param messageParams 消息参数
*/
public static void assertServiceException(Executable executable, ErrorCode errorCode, Object... messageParams) {
// 调用方法
ServiceException serviceException = assertThrows(ServiceException.class, executable);
// 校验错误码
Assertions.assertEquals(errorCode.getCode(), serviceException.getCode(), "错误码不匹配");
String message = ServiceExceptionUtil.doFormat(errorCode.getCode(), errorCode.getMsg(), messageParams);
Assertions.assertEquals(message, serviceException.getMessage(), "错误提示不匹配");
}
}

View File

@@ -1,4 +0,0 @@
/**
* 测试组件,用于单元测试、集成测试等等
*/
package com.lideeyunji.tool.framework.test;