refactor(test): 重构测试套件结构并优化测试配置

feat(test-suite): 新增测试套件模块,包含API测试客户端和测试配置
fix(api): 修复数据库实体和仓库的删除操作返回值
style(api): 统一数据库表名和字段命名
perf(api): 添加缓存注解提升配置查询性能
test(api): 添加H2测试数据库配置支持
chore: 清理旧的测试文件和脚本
This commit is contained in:
张翔
2026-04-01 20:57:24 +08:00
parent 24422c2c19
commit 1e3dc11d59
180 changed files with 15421 additions and 3797 deletions
@@ -35,8 +35,24 @@ import static org.springframework.web.reactive.function.server.RouterFunctions.r
public class SystemRouter {
@Bean
public RouterFunction<ServerResponse> dictionaryRoutes(DictionaryHandler dictionaryHandler) {
public RouterFunction<ServerResponse> systemRoutes(
DictionaryHandler dictionaryHandler,
SysUserHandler userHandler,
MenuHandler menuHandler,
SysRoleHandler roleHandler,
SysConfigHandler configHandler,
SysLogHandler logHandler,
OperationLogHandler operationLogHandler,
SysAuthHandler authHandler,
StatsHandler statsHandler,
SysDictHandler dictHandler,
SysNoticeHandler noticeHandler,
SysUserMessageHandler messageHandler,
SysFileHandler fileHandler,
SysPermissionHandler permissionHandler) {
return route()
// ========== 字典路由 ==========
.GET("/api/dictionaries", dictionaryHandler::getAllDictionaries)
.GET("/api/dictionaries/{id}", dictionaryHandler::getDictionaryById)
.GET("/api/dictionaries/type/{type}", dictionaryHandler::getDictionariesByType)
@@ -44,47 +60,35 @@ public class SystemRouter {
.POST("/api/dictionaries", dictionaryHandler::createDictionary)
.PUT("/api/dictionaries/{id}", dictionaryHandler::updateDictionary)
.DELETE("/api/dictionaries/{id}", dictionaryHandler::deleteDictionary)
.build();
}
@Bean
public RouterFunction<ServerResponse> userRoutes(SysUserHandler userHandler) {
return route()
// ========== 用户路由 ==========
.GET("/api/users", userHandler::getAllUsers)
.GET("/api/users/page", userHandler::getUsersByPage)
.GET("/api/users/count", userHandler::getUserCount)
.GET("/api/users/{id}", userHandler::getUserById)
.GET("/api/users/username/{username}", userHandler::getUserByUsername)
.POST("/api/users", userHandler::createUser)
.PUT("/api/users/{id}", userHandler::updateUser)
.DELETE("/api/users/{id}", userHandler::deleteUser)
.POST("/api/users/{id}/password", userHandler::changePassword)
.DELETE("/api/users/{id}/logical", userHandler::logicalDeleteUser)
.POST("/api/users/logical-delete", userHandler::logicalDeleteUsers)
.POST("/api/users/{id}/restore", userHandler::restoreUser)
.POST("/api/users/restore", userHandler::restoreUsers)
.GET("/api/users/check/username", userHandler::checkUsernameExists)
.GET("/api/users/check/email", userHandler::checkEmailExists)
.POST("/api/users/{id}/roles", userHandler::assignRoles)
.POST("/api/users", userHandler::createUser)
.GET("/api/users/{id}", userHandler::getUserById)
.PUT("/api/users/{id}", userHandler::updateUser)
.DELETE("/api/users/{id}", userHandler::deleteUser)
.POST("/api/users/{id}/action/change-password", userHandler::changePassword)
.POST("/api/users/{id}/action/logical-delete", userHandler::logicalDeleteUser)
.POST("/api/users/logical-delete", userHandler::logicalDeleteUsers)
.POST("/api/users/action/restore", userHandler::restoreUsers)
.POST("/api/users/{id}/action/restore", userHandler::restoreUser)
.GET("/api/users/{id}/roles", userHandler::getUserRoles)
.build();
}
@Bean
public RouterFunction<ServerResponse> menuRoutes(MenuHandler menuHandler) {
return route()
.POST("/api/users/{id}/roles", userHandler::assignRoles)
// ========== 菜单路由 ==========
.GET("/api/menus", menuHandler::getAllMenus)
.GET("/api/menus/tree", menuHandler::getMenuTree)
.GET("/api/menus/{id}", menuHandler::getMenuById)
.POST("/api/menus", menuHandler::createMenu)
.PUT("/api/menus/{id}", menuHandler::updateMenu)
.DELETE("/api/menus/{id}", menuHandler::deleteMenu)
.build();
}
@Bean
public RouterFunction<ServerResponse> roleRoutes(SysRoleHandler roleHandler, SysPermissionHandler permissionHandler) {
return route()
// ========== 角色路由 ==========
.GET("/api/roles", roleHandler::getAllRoles)
.GET("/api/roles/page", roleHandler::getRolesByPage)
.GET("/api/roles/count", roleHandler::getRoleCount)
@@ -97,24 +101,16 @@ public class SystemRouter {
.POST("/api/roles/{id}/restore", roleHandler::restoreRole)
.GET("/api/roles/{id}/permissions", permissionHandler::getPermissionsByRoleId)
.POST("/api/roles/{id}/permissions", permissionHandler::assignPermissionsToRole)
.build();
}
@Bean
public RouterFunction<ServerResponse> configRoutes(SysConfigHandler configHandler) {
return route()
// ========== 配置路由 ==========
.GET("/api/config", configHandler::getAllConfigs)
.GET("/api/config/{id}", configHandler::getConfigById)
.GET("/api/config/key/{configKey}", configHandler::getConfigByKey)
.POST("/api/config", configHandler::createConfig)
.PUT("/api/config/{id}", configHandler::updateConfig)
.DELETE("/api/config/{id}", configHandler::deleteConfig)
.build();
}
@Bean
public RouterFunction<ServerResponse> logRoutes(SysLogHandler logHandler) {
return route()
// ========== 日志路由 ==========
.GET("/api/logs/login", logHandler::getAllLoginLogs)
.GET("/api/logs/login/page", logHandler::getLoginLogsByPage)
.GET("/api/logs/login/count", logHandler::getLoginLogCount)
@@ -126,39 +122,21 @@ public class SystemRouter {
.GET("/api/logs/exception/count", logHandler::getExceptionLogCount)
.GET("/api/logs/exception/{id}", logHandler::getExceptionLogById)
.POST("/api/logs/exception", logHandler::createExceptionLog)
.build();
}
@Bean
public RouterFunction<ServerResponse> operationLogRoutes(OperationLogHandler operationLogHandler) {
return route()
.GET("/api/logs/operation", operationLogHandler::getAllOperationLogs)
.GET("/api/logs/operation/page", operationLogHandler::getOperationLogsByPage)
.GET("/api/logs/operation/count", operationLogHandler::getOperationLogCount)
.GET("/api/logs/operation/{id}", operationLogHandler::getOperationLogById)
.POST("/api/logs/operation", operationLogHandler::createOperationLog)
.build();
}
@Bean
public RouterFunction<ServerResponse> authRoutes(SysAuthHandler authHandler) {
return route()
// ========== 认证路由 ==========
.POST("/api/auth/login", authHandler::login)
.POST("/api/auth/register", authHandler::register)
.POST("/api/auth/logout", authHandler::logout)
.build();
}
@Bean
public RouterFunction<ServerResponse> statsRoutes(StatsHandler statsHandler) {
return route()
// ========== 统计路由 ==========
.GET("/api/stats/overview", statsHandler::getOverview)
.build();
}
@Bean
public RouterFunction<ServerResponse> dictRoutes(SysDictHandler dictHandler) {
return route()
// ========== 数据字典路由 ==========
.GET("/api/dict/types", dictHandler::getAllDictTypes)
.GET("/api/dict/types/{id}", dictHandler::getDictTypeById)
.GET("/api/dict/types/type/{dictType}", dictHandler::getDictTypeByType)
@@ -171,36 +149,24 @@ public class SystemRouter {
.POST("/api/dict/data", dictHandler::createDictData)
.PUT("/api/dict/data/{id}", dictHandler::updateDictData)
.DELETE("/api/dict/data/{id}", dictHandler::deleteDictData)
.build();
}
@Bean
public RouterFunction<ServerResponse> noticeRoutes(SysNoticeHandler noticeHandler) {
return route()
// ========== 公告路由 ==========
.GET("/api/notices", noticeHandler::getAllNotices)
.GET("/api/notices/{id}", noticeHandler::getNoticeById)
.GET("/api/notices/status/{status}", noticeHandler::getNoticesByStatus)
.POST("/api/notices", noticeHandler::createNotice)
.PUT("/api/notices/{id}", noticeHandler::updateNotice)
.DELETE("/api/notices/{id}", noticeHandler::deleteNotice)
.build();
}
@Bean
public RouterFunction<ServerResponse> messageRoutes(SysUserMessageHandler messageHandler) {
return route()
// ========== 消息路由 ==========
.GET("/api/messages/user/{userId}", messageHandler::getMessagesByUser)
.GET("/api/messages/user/{userId}/unread", messageHandler::getUnreadCount)
.GET("/api/messages/user/{userId}/unread/list", messageHandler::getUnreadList)
.POST("/api/messages", messageHandler::createMessage)
.PUT("/api/messages/{id}/read", messageHandler::markAsRead)
.DELETE("/api/messages/{id}", messageHandler::deleteMessage)
.build();
}
@Bean
public RouterFunction<ServerResponse> fileRoutes(SysFileHandler fileHandler) {
return route()
// ========== 文件路由 ==========
.GET("/api/files", fileHandler::getAllFiles)
.GET("/api/files/{id}", fileHandler::getFileById)
.POST("/api/files/upload", fileHandler::uploadFile)
@@ -209,12 +175,8 @@ public class SystemRouter {
.GET("/api/files/{id}/preview", fileHandler::previewFile)
.GET("/api/files/preview/{fileName}", fileHandler::previewFileByName)
.DELETE("/api/files/{id}", fileHandler::deleteFile)
.build();
}
@Bean
public RouterFunction<ServerResponse> permissionRoutes(SysPermissionHandler permissionHandler) {
return route()
// ========== 权限路由 ==========
.GET("/api/permissions", permissionHandler::getAllPermissions)
.GET("/api/permissions/{id}", permissionHandler::getPermissionById)
.GET("/api/permissions/code/{code}", permissionHandler::getPermissionByCode)
@@ -223,6 +185,7 @@ public class SystemRouter {
.POST("/api/permissions", permissionHandler::createPermission)
.PUT("/api/permissions/{id}", permissionHandler::updatePermission)
.DELETE("/api/permissions/{id}", permissionHandler::deletePermission)
.build();
}
}
}
@@ -0,0 +1,52 @@
# H2数据库配置(用于测试环境)
spring:
r2dbc:
url: r2dbc:h2:mem:///testdb
username: sa
password:
pool:
initial-size: 5
max-size: 20
max-idle-time: 30m
max-life-time: 1h
acquire-timeout: 5s
datasource:
url: jdbc:h2:mem:testdb
username: sa
password:
driver-class-name: org.h2.Driver
h2:
console:
enabled: true
path: /h2-console
settings:
web-allow-others: true
flyway:
enabled: false
sql:
init:
mode: always
continue-on-error: true
# 测试专用配置
test:
database:
type: h2
in-memory: true
cleanup:
enabled: true
strategy: truncate
# 日志配置
logging:
level:
cn.novalon.manage: DEBUG
org.springframework.r2dbc: DEBUG
org.springframework.jdbc: DEBUG
org.flywaydb: INFO
com.h2database: WARN
@@ -1,22 +1,65 @@
server:
port: 8084
spring:
application:
name: manage-app
r2dbc:
url: r2dbc:h2:mem://testdb;MODE=PostgreSQL;DATABASE_TO_LOWER=TRUE
username: sa
password:
url: r2dbc:postgresql://localhost:55432/manage_system
username: novalon
password: novalon123
pool:
initial-size: 5
max-size: 20
max-idle-time: 30m
max-life-time: 1h
acquire-timeout: 5s
datasource:
url: jdbc:postgresql://localhost:55432/manage_system
username: novalon
password: novalon123
driver-class-name: org.postgresql.Driver
flyway:
enabled: true
enabled: false
h2:
console:
enabled: true
path: /h2-console
security:
user:
name: disabled
password: disabled
rate:
limit:
limit-for-period: 10000
limit-refresh-period: 1s
timeout-duration: 0
management:
endpoints:
web:
exposure:
include: health,info,metrics,env,loggers
base-path: /actuator
endpoint:
health:
show-details: always
metrics:
tags:
application: ${spring.application.name}
environment: ${spring.profiles.active}
logging:
level:
cn.novalon.manage: DEBUG
org.springframework.r2dbc: DEBUG
org.springframework.web: TRACE
cn.novalon.manage.db: DEBUG
org.flywaydb: INFO
springdoc:
api-docs:
path: /api-docs
enabled: true
swagger-ui:
path: /swagger-ui.html
enabled: true
tags-sorter: alpha
operations-sorter: alpha
show-actuator: false
default-consumes-media-type: application/json
default-produces-media-type: application/json
@@ -0,0 +1,30 @@
╔═══════════════════════════════════════════════════════════════════╗
║ ║
║ ███╗ ██╗ ██████╗ ██╗ ██╗ █████╗ ██╗ ██████╗ ███╗ ██╗ ║
║ ████╗ ██║██╔═══██╗██║ ██║██╔══██╗██║ ██╔═══██╗████╗ ██║ ║
║ ██╔██╗ ██║██║ ██║██║ ██║███████║██║ ██║ ██║██╔██╗ ██║ ║
║ ██║╚██╗██║██║ ██║╚██╗ ██╔╝██╔══██║██║ ██║ ██║██║╚██╗██║ ║
║ ██║ ╚████║╚██████╔╝ ╚████╔╝ ██║ ██║███████╗╚██████╔╝██║ ╚████║ ║
║ ╚═╝ ╚═══╝ ╚═════╝ ╚═══╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═══╝ ║
║ ║
║ ███╗ ███╗ █████╗ ███╗ ██╗ █████╗ ██████╗ ███████╗ ║
║ ████╗ ████║██╔══██╗████╗ ██║██╔══██╗██╔════╝ ██╔════╝ ║
║ ██╔████╔██║███████║██╔██╗ ██║███████║██║ ███╗█████╗ ║
║ ██║╚██╔╝██║██╔══██║██║╚██╗██║██╔══██║██║ ██║██╔══╝ ║
║ ██║ ╚═╝ ██║██║ ██║██║ ╚████║██║ ██║╚██████╔╝███████╗ ║
║ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝ ║
║ ║
║ ███████╗██╗ ██╗███████╗████████╗███████╗███╗ ███╗ ║
║ ██╔════╝╚██╗ ██╔╝██╔════╝╚══██╔══╝██╔════╝████╗ ████║ ║
║ ███████╗ ╚████╔╝ ███████╗ ██║ █████╗ ██╔████╔██║ ║
║ ╚════██║ ╚██╔╝ ╚════██║ ██║ ██╔══╝ ██║╚██╔╝██║ ║
║ ███████║ ██║ ███████║ ██║ ███████╗██║ ╚═╝ ██║ ║
║ ╚══════╝ ╚═╝ ╚══════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ║
║ ║
╚═══════════════════════════════════════════════════════════════════╝
:: Novalon Manage System ::
Version: ${application.version:Unknown}
Spring Boot: ${spring-boot.version}
Java: ${java.version}
PID: ${PID}