# 测试指南 **本文引用的文件** - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [application.yml](file://crm-app/src/main/resources/application.yml) - [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java) - [SystemController.java](file://crm-auth/src/main/java/com/crm/auth/controller/SystemController.java) - [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java) - [PermissionConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/PermissionConfig.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [AuthLoginUser.java](file://crm-auth/src/main/java/com/crm/auth/security/AuthLoginUser.java) - [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java) - [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java) - [AuthServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java) - [AuthUserServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthUserServiceImpl.java) - [SysDeptServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysDeptServiceImpl.java) - [DingTalkAuthClient.java](file://crm-auth/src/main/java/com/crm/auth/service/client/DingTalkAuthClient.java) - [ThirdPartyAuthClientFactory.java](file://crm-auth/src/main/java/com/crm/auth/service/client/ThirdPartyAuthClientFactory.java) - [DataScopeIntegrationTest.java](file://crm-auth/src/test/java/com/crm/auth/security/scope/DataScopeIntegrationTest.java) - [TestOwnedData.java](file://crm-auth/src/test/java/com/crm/auth/security/scope/TestOwnedData.java) - [TestOwnedDataMapper.java](file://crm-auth/src/test/java/com/crm/auth/security/scope/TestOwnedDataMapper.java) - [DingTalkAuthClientTest.java](file://crm-auth/src/test/java/com/crm/auth/service/client/DingTalkAuthClientTest.java) - [ThirdPartyAuthClientFactoryTest.java](file://crm-auth/src/test/java/com/crm/auth/service/client/ThirdPartyAuthClientFactoryTest.java) - [AuthServiceImplTest.java](file://crm-auth/src/test/java/com/crm/auth/service/impl/AuthServiceImplTest.java) - [AuthUserServiceImplTest.java](file://crm-auth/src/test/java/com/crm/auth/service/impl/AuthUserServiceImplTest.java) - [SysDeptServiceImplTest.java](file://crm-auth/src/test/java/com/crm/auth/service/impl/SysDeptServiceImplTest.java) - [UserListIntegrationTest.java](file://crm-auth/src/test/java/com/crm/auth/service/impl/UserListIntegrationTest.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [BusinessErrorException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/BusinessErrorException.java) - [MissingParameterException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/MissingParameterException.java) - [PermissionErrorException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/PermissionErrorException.java) - [ResourceNotExistException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/ResourceNotExistException.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java) - [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java) - [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java) - [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java) - [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java) - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java) - [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java) - [DataVisibilityTest.java](file://crm-base/src/test/java/com/crm/base/security/DataVisibilityTest.java) - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java) - [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java) - [OrphanChunkCleanupTask.java](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java) - [FileApiImplTest.java](file://crm-file/src/test/java/com/crm/file/service/impl/FileApiImplTest.java) - [KkFileViewClientTest.java](file://crm-file/src/test/java/com/crm/file/service/KkFileViewClientTest.java) - [OrphanChunkCleanupTaskTest.java](file://crm-file/src/test/java/com/crm/file/task/OrphanChunkCleanupTaskTest.java) ## 更新摘要 **变更内容** - 新增用户列表集成测试章节,详细介绍UserListIntegrationTest的使用方法和最佳实践 - 扩展数据权限集成测试部分,补充DataScopeIntegrationTest的测试场景和断言方法 - 更新集成测试策略,增加复杂业务场景的测试覆盖建议 ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考虑](#性能考虑) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本测试指南面向CRM后端项目的开发者与测试工程师,目标是建立覆盖单元测试、集成测试、端到端测试的完整体系。文档围绕认证授权、权限控制、文件操作、异常处理等核心能力,给出Mock策略、测试数据准备、测试环境搭建、覆盖率要求与持续集成建议,并补充性能、压力与安全测试的方法与工具推荐,帮助团队构建稳定可靠的测试质量保障流程。 ## 项目结构 本项目采用多模块Maven工程: - crm-app:应用启动入口与全局配置 - crm-auth:认证与权限(控制器、安全配置、服务实现、客户端) - crm-base:基础能力(异常、结果封装、通用实体、安全上下文、MyBatis-Plus配置等) - crm-file:文件上传下载与预览、分片清理任务 ```mermaid graph TB subgraph "应用层" APP["crm-app
启动类与应用配置"] end subgraph "认证与权限" AUTH_CTRL["AuthController / SystemController"] AUTH_SEC["SecurityConfig / JwtAuthenticationFilter / TokenService"] AUTH_SVC["AuthServiceImpl / AuthUserServiceImpl / SysDeptServiceImpl"] AUTH_CLIENT["DingTalkAuthClient / ThirdPartyAuthClientFactory"] end subgraph "基础能力" BASE_EXC["GlobalExceptionHandlerAdvice / 业务异常类"] BASE_RESULT["Result / ResultCodeEnum / PageResult"] BASE_SEC["DataScopeHelper / DataVisibilityContext / SecurityUtils"] BASE_ENT["BaseEntity / OwnedEntity"] end subgraph "文件服务" FILE_CTRL["FileController"] FILE_SVC["FileApiImpl / FileInfoServiceImpl"] FILE_TASK["OrphanChunkCleanupTask"] FILE_EXT["KkFileViewClient"] end APP --> AUTH_CTRL AUTH_CTRL --> AUTH_SEC AUTH_CTRL --> AUTH_SVC AUTH_SVC --> BASE_ENT AUTH_SEC --> BASE_SEC AUTH_SVC --> BASE_EXC AUTH_SVC --> BASE_RESULT FILE_CTRL --> FILE_SVC FILE_SVC --> FILE_EXT FILE_SVC --> BASE_RESULT FILE_TASK --> FILE_SVC ``` 图表来源 - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java) - [SystemController.java](file://crm-auth/src/main/java/com/crm/auth/controller/SystemController.java) - [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [AuthServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java) - [AuthUserServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthUserServiceImpl.java) - [SysDeptServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysDeptServiceImpl.java) - [DingTalkAuthClient.java](file://crm-auth/src/main/java/com/crm/auth/service/client/DingTalkAuthClient.java) - [ThirdPartyAuthClientFactory.java](file://crm-auth/src/main/java/com/crm/auth/service/client/ThirdPartyAuthClientFactory.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [BusinessErrorException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/BusinessErrorException.java) - [PermissionErrorException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/PermissionErrorException.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java) - [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java) - [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java) - [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java) - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java) - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java) - [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java) - [OrphanChunkCleanupTask.java](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java) 章节来源 - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [application.yml](file://crm-app/src/main/resources/application.yml) ## 核心组件 - 认证与鉴权 - 控制器:登录、系统信息接口 - 安全配置:JWT过滤器、令牌服务、权限拦截器 - 服务层:用户认证、部门树、角色菜单权限 - 第三方登录:钉钉等OAuth客户端与工厂 - 基础能力 - 统一异常处理与业务异常类型 - 统一返回体与分页对象 - 数据权限上下文与工具方法 - 通用实体基类 - 文件服务 - 文件上传/下载/预览 - 分片清理定时任务 - 外部预览服务客户端 章节来源 - [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java) - [SystemController.java](file://crm-auth/src/main/java/com/crm/auth/controller/SystemController.java) - [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [AuthServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java) - [AuthUserServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthUserServiceImpl.java) - [SysDeptServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysDeptServiceImpl.java) - [DingTalkAuthClient.java](file://crm-auth/src/main/java/com/crm/auth/service/client/DingTalkAuthAuthClient.java) - [ThirdPartyAuthClientFactory.java](file://crm-auth/src/main/java/com/crm/auth/service/client/ThirdPartyAuthClientFactory.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [BusinessErrorException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/BusinessErrorException.java) - [PermissionErrorException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/PermissionErrorException.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java) - [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java) - [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java) - [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java) - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java) - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java) - [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java) - [OrphanChunkCleanupTask.java](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java) ## 架构总览 下图展示请求从Web层到安全层、服务层与外部依赖的关键路径,以及异常与返回体的流转。 ```mermaid sequenceDiagram participant Client as "客户端" participant Controller as "AuthController/SystemController" participant Filter as "JwtAuthenticationFilter" participant TokenSvc as "TokenService" participant Service as "AuthServiceImpl/AuthUserServiceImpl" participant BaseEx as "GlobalExceptionHandlerAdvice" participant Resp as "Result/PageResult" Client->>Controller : "HTTP请求(含Token)" Controller->>Filter : "进入安全过滤链" Filter->>TokenSvc : "解析/校验Token" TokenSvc-->>Filter : "用户上下文" Filter-->>Controller : "放行或拒绝" Controller->>Service : "调用业务逻辑" Service-->>Controller : "返回业务结果" Controller-->>Resp : "封装为统一响应" Note over Controller,Resp : "正常路径" Service-->>BaseEx : "抛出业务异常" BaseEx-->>Resp : "统一错误响应" Resp-->>Client : "HTTP响应" ``` 图表来源 - [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java) - [SystemController.java](file://crm-auth/src/main/java/com/crm/auth/controller/SystemController.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [AuthServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java) - [AuthUserServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthUserServiceImpl.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java) ## 详细组件分析 ### 认证与权限测试要点 - 单元测试 - 对TokenService进行Mock,验证Token生成、解析、过期判断分支 - 对AuthServiceImpl进行Mock,覆盖登录成功/失败、密码校验、第三方登录回调 - 对DingTalkAuthClient与ThirdPartyAuthClientFactory进行Mock,模拟第三方响应与异常 - 集成测试 - 使用SpringBootTest加载安全配置,构造JWT并发起请求,验证鉴权通过与否 - 使用@Sql或内存数据库初始化用户、角色、菜单数据,验证权限判定与数据范围 - 端到端测试 - 使用RestTemplate或WebTestClient发起登录、获取用户信息、受限资源访问等场景 - 断言HTTP状态码、统一响应结构与字段 ```mermaid classDiagram class AuthController { +登录() +获取用户信息() } class JwtAuthenticationFilter { +doFilter() } class TokenService { +生成Token() +解析Token() +校验Token() } class AuthServiceImpl { +登录() +查询用户() } class DingTalkAuthClient { +获取用户信息() } class ThirdPartyAuthClientFactory { +创建客户端() } AuthController --> JwtAuthenticationFilter : "受保护" JwtAuthenticationFilter --> TokenService : "解析/校验" AuthController --> AuthServiceImpl : "调用" AuthServiceImpl --> DingTalkAuthClient : "第三方登录" AuthServiceImpl --> ThirdPartyAuthClientFactory : "选择客户端" ``` 图表来源 - [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [AuthServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java) - [DingTalkAuthClient.java](file://crm-auth/src/main/java/com/crm/auth/service/client/DingTalkAuthClient.java) - [ThirdPartyAuthClientFactory.java](file://crm-auth/src/main/java/com/crm/auth/service/client/ThirdPartyAuthClientFactory.java) 章节来源 - [AuthServiceImplTest.java](file://crm-auth/src/test/java/com/crm/auth/service/impl/AuthServiceImplTest.java) - [AuthUserServiceImplTest.java](file://crm-auth/src/test/java/com/crm/auth/service/impl/AuthUserServiceImplTest.java) - [DingTalkAuthClientTest.java](file://crm-auth/src/test/java/com/crm/auth/service/client/DingTalkAuthClientTest.java) - [ThirdPartyAuthClientFactoryTest.java](file://crm-auth/src/test/java/com/crm/auth/service/client/ThirdPartyAuthClientFactoryTest.java) ### 用户列表集成测试要点 **新增** 针对用户列表功能的全面集成测试,确保复杂查询场景的正确性 - 测试场景覆盖 - 用户列表分页查询:验证分页参数、排序规则、数据完整性 - 条件筛选测试:用户名、邮箱、状态等多条件组合查询 - 权限控制测试:不同角色用户的可见范围和数据隔离 - 性能测试:大数据量下的查询性能和响应时间 - 测试数据准备 - 使用@Sql脚本批量插入测试用户数据 - 模拟不同部门和角色的用户关系 - 准备边界条件和异常场景数据 - 断言策略 - 验证返回数据的结构和字段完整性 - 检查分页信息的准确性(总数、页码、每页大小) - 确认权限控制生效,用户只能看到授权范围内的数据 ```mermaid flowchart TD Start(["用户列表查询请求"]) --> ParseParams["解析查询参数"] ParseParams --> ValidatePerm["验证用户权限"] ValidatePerm --> BuildQuery["构建查询条件"] BuildQuery --> ExecuteQuery["执行数据库查询"] ExecuteQuery --> ApplyPagination["应用分页处理"] ApplyPagination --> FormatResponse["格式化响应数据"] FormatResponse --> Return["返回结果"] ``` 图表来源 - [UserListIntegrationTest.java](file://crm-auth/src/test/java/com/crm/auth/service/impl/UserListIntegrationTest.java) - [AuthUserServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthUserServiceImpl.java) - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) 章节来源 - [UserListIntegrationTest.java](file://crm-auth/src/test/java/com/crm/auth/service/impl/UserListIntegrationTest.java) ### 数据权限与可见性测试要点 - 单元测试 - 对DataScopeHelper与DataVisibilityContext进行Mock,验证不同数据范围下的SQL拼接与上下文切换 - 对OwnedEntity与BaseEntity进行Mock,验证数据归属字段填充 - 集成测试 - 使用@DataScope注解与拦截器,构造不同用户与部门关系,验证查询结果集隔离 - 使用DataScopeIntegrationTest作为参考,结合测试实体与Mapper验证数据范围生效 - **扩展测试场景**:新增复杂的数据权限组合测试,包括多层级部门、跨部门数据共享等场景 - 端到端测试 - 以不同身份登录,访问同一接口,断言返回数据仅包含当前用户可访问范围 ```mermaid flowchart TD Start(["进入受保护接口"]) --> CheckScope["读取数据权限上下文"] CheckScope --> ScopeType{"数据范围类型"} ScopeType --> |个人| BuildPersonal["拼接个人数据条件"] ScopeType --> |部门| BuildDept["拼接部门数据条件"] ScopeType --> |全部| NoFilter["不添加过滤条件"] BuildPersonal --> Apply["应用到查询语句"] BuildDept --> Apply NoFilter --> Apply Apply --> Execute["执行查询并返回结果"] Execute --> End(["结束"]) ``` 图表来源 - [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java) - [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java) - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java) - [DataScopeIntegrationTest.java](file://crm-auth/src/test/java/com/crm/auth/security/scope/DataScopeIntegrationTest.java) - [TestOwnedData.java](file://crm-auth/src/test/java/com/crm/auth/security/scope/TestOwnedData.java) - [TestOwnedDataMapper.java](file://crm-auth/src/test/java/com/crm/auth/security/scope/TestOwnedDataMapper.java) 章节来源 - [DataScopeIntegrationTest.java](file://crm-auth/src/test/java/com/crm/auth/security/scope/DataScopeIntegrationTest.java) - [DataVisibilityTest.java](file://crm-base/src/test/java/com/crm/base/security/DataVisibilityTest.java) ### 文件服务测试要点 - 单元测试 - 对FileApiImpl与FileInfoServiceImpl进行Mock,验证上传会话创建、分片合并、元数据持久化 - 对KkFileViewClient进行Mock,模拟预览服务响应与超时/错误 - 对OrphanChunkCleanupTask进行Mock,验证分片清理逻辑与调度触发 - 集成测试 - 使用内存文件系统或Minio测试容器,验证真实上传下载流程 - 使用@Sql初始化文件记录,断言查询与删除行为 - 端到端测试 - 通过FileController上传大文件、断点续传、下载与预览,验证网络中断恢复与进度反馈 ```mermaid sequenceDiagram participant Client as "客户端" participant FileCtrl as "FileController" participant FileSvc as "FileApiImpl/FileInfoServiceImpl" participant Minio as "对象存储" participant Preview as "KkFileViewClient" Client->>FileCtrl : "POST 上传/分片上传" FileCtrl->>FileSvc : "创建会话/保存分片" FileSvc->>Minio : "写入分片" FileSvc-->>FileCtrl : "返回会话ID" Client->>FileCtrl : "POST 合并分片" FileCtrl->>FileSvc : "合并并生成文件信息" FileSvc->>Minio : "合并分片" FileSvc-->>Client : "返回文件URL" Client->>Preview : "GET 预览链接" Preview-->>Client : "返回预览地址" ``` 图表来源 - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java) - [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java) - [OrphanChunkCleanupTask.java](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java) 章节来源 - [FileApiImplTest.java](file://crm-file/src/test/java/com/crm/file/service/impl/FileApiImplTest.java) - [KkFileViewClientTest.java](file://crm-file/src/test/java/com/crm/file/service/KkFileViewClientTest.java) - [OrphanChunkCleanupTaskTest.java](file://crm-file/src/test/java/com/crm/file/task/OrphanChunkCleanupTaskTest.java) ### 异常处理与统一响应测试要点 - 单元测试 - 对GlobalExceptionHandlerAdvice进行Mock,验证各业务异常映射到统一Result结构 - 对Result与ResultCodeEnum进行断言,确保错误码与消息一致性 - 集成测试 - 在控制器或服务中抛出MissingParameterException、PermissionErrorException、ResourceNotExistException等,验证全局异常处理器捕获并返回正确HTTP状态码 - 端到端测试 - 构造非法参数、越权访问、资源不存在等场景,断言响应体中的code、message、data字段 ```mermaid flowchart TD Entry(["业务方法抛出异常"]) --> Catch["全局异常处理器捕获"] Catch --> Classify{"异常类型分类"} Classify --> |参数缺失| ParamErr["参数缺失错误"] Classify --> |权限不足| PermErr["权限错误"] Classify --> |资源不存在| ResErr["资源不存在错误"] Classify --> |其他业务| BizErr["业务错误"] ParamErr --> Wrap["封装为Result"] PermErr --> Wrap ResErr --> Wrap BizErr --> Wrap Wrap --> Return(["返回统一响应"]) ``` 图表来源 - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [BusinessErrorException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/BusinessErrorException.java) - [MissingParameterException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/MissingParameterException.java) - [PermissionErrorException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/PermissionErrorException.java) - [ResourceNotExistException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/ResourceNotExistException.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java) 章节来源 - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java) ## 依赖关系分析 - 模块内依赖 - crm-auth依赖crm-base(异常、结果、安全上下文、实体基类) - crm-file依赖crm-base(结果、实体基类) - 外部依赖 - JWT与Spring Security用于认证与鉴权 - MyBatis-Plus用于数据访问 - 对象存储(如MinIO)用于文件存储 - 第三方登录(钉钉等)与预览服务(KKFileView) ```mermaid graph LR CRM_APP["crm-app"] --> CRM_AUTH["crm-auth"] CRM_APP --> CRM_FILE["crm-file"] CRM_AUTH --> CRM_BASE["crm-base"] CRM_FILE --> CRM_BASE["crm-base"] CRM_AUTH --> EXT_OAUTH["第三方登录(OAuth)"] CRM_FILE --> EXT_STORE["对象存储(MinIO)"] CRM_FILE --> EXT_PREVIEW["预览服务(KKFileView)"] ``` 图表来源 - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java) - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) 章节来源 - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) ## 性能考虑 - 单元测试 - 避免I/O与网络调用,使用Mock减少耗时;对复杂算法进行边界值与大数据量输入测试 - 集成测试 - 使用内存数据库或测试容器缩短启动时间;合理设置事务回滚与数据隔离 - 对文件上传/下载进行流式处理与分片大小调优测试 - **新增** 对用户列表等复杂查询进行性能基准测试,监控SQL执行时间和数据库负载 - 端到端测试 - 使用轻量级客户端并发模拟,关注接口响应时间与吞吐 - 性能与压力测试 - 使用JMeter或Gatling进行压测,设计阶梯加压与长稳态场景 - 监控CPU、内存、GC、线程池、连接池与慢SQL - 安全测试 - 使用OWASP ZAP或Burp Suite进行漏洞扫描与渗透测试 - 针对JWT伪造、越权、注入、XSS等进行专项用例 ## 故障排查指南 - 常见问题定位 - 认证失败:检查JWT签名、过期时间、过滤器链顺序与白名单配置 - 权限不足:确认用户角色、菜单权限与数据范围上下文是否正确设置 - 文件上传失败:检查分片大小、存储桶权限、网络超时与重试策略 - 异常未捕获:确认全局异常处理器是否注册、异常类型是否匹配 - **新增** 用户列表查询问题:检查数据权限配置、SQL条件拼接、分页参数处理 - 调试建议 - 开启DEBUG日志,打印关键上下文(用户ID、角色、数据范围、请求ID) - 使用Mock验证外部依赖行为,逐步缩小问题范围 - 使用集成测试复现问题,结合数据库快照与缓存状态对比 章节来源 - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) ## 结论 通过分层测试策略(单元、集成、端到端)、完善的Mock与测试数据管理、严格的覆盖率与持续集成规范,以及对认证、权限、文件、异常等核心能力的专项测试,可以显著提升代码质量与系统稳定性。新增的用户列表集成测试进一步增强了复杂业务场景的测试覆盖。建议将性能、压力与安全测试纳入常规流水线,形成闭环的质量保障体系。 ## 附录 ### 测试环境与数据准备 - 使用SpringBootTest加载最小化配置,启用内存数据库与Redis测试容器 - 使用@Sql或脚本初始化用户、角色、菜单、部门等基础数据 - 使用@DirtiesContext控制测试间上下文隔离,避免状态污染 - **新增** 用户列表测试数据准备:批量创建不同部门、角色的用户数据,模拟真实业务场景 章节来源 - [application.yml](file://crm-app/src/main/resources/application.yml) ### Mock策略与最佳实践 - 对外部依赖(第三方登录、对象存储、预览服务)一律Mock,保证测试快速稳定 - 对内部服务与方法使用@MockBean或构造器注入Mock,明确期望行为与返回值 - 对安全上下文与权限相关逻辑,使用测试辅助类或自定义注解简化设置 - **新增** 用户列表测试Mock策略:Mock数据库查询、权限验证、数据转换等依赖 章节来源 - [DingTalkAuthClientTest.java](file://crm-auth/src/test/java/com/crm/auth/service/client/DingTalkAuthClientTest.java) - [ThirdPartyAuthClientFactoryTest.java](file://crm-auth/src/test/java/com/crm/auth/service/client/ThirdPartyAuthClientFactoryTest.java) - [FileApiImplTest.java](file://crm-file/src/test/java/com/crm/file/service/impl/FileApiImplTest.java) - [KkFileViewClientTest.java](file://crm-file/src/test/java/com/crm/file/service/KkFileViewClientTest.java) ### 测试覆盖率要求 - 行覆盖率≥80%,分支覆盖率≥70%,关键模块(认证、权限、文件)≥90% - 使用JaCoCo生成报告,并在CI中阻断低覆盖率提交 - **新增** 用户列表功能覆盖率要求:查询逻辑、权限控制、分页处理等核心路径覆盖率≥95% ### 持续集成配置建议 - 在CI中执行mvn test与覆盖率聚合,失败则阻断流水线 - 并行执行单元测试与集成测试,缩短构建时间 - 生成测试报告与覆盖率HTML,归档至制品库 - **新增** 集成测试优化:使用测试容器加速数据库和Redis初始化 ### 性能与压力测试工具推荐 - JMeter/Gatling:编写脚本模拟高并发登录、文件上传与下载 - Prometheus+Grafana:采集指标与可视化监控 - APM工具(SkyWalking/Arthas):链路追踪与线上诊断 - **新增** SQL性能分析:使用MyBatis-Plus的性能监控插件分析慢查询 ### 安全测试方法与工具 - OWASP ZAP/Burp Suite:自动化漏洞扫描与手动渗透 - 依赖漏洞扫描(Dependabot/SonarQube):检测第三方库风险 - 敏感信息与密钥管理:使用环境变量与密钥管理服务 - **新增** 权限测试:验证水平越权、垂直越权、数据范围绕过等安全场景