# 集成测试

<cite>
**本文引用的文件**
- [tests/conftest.py](file://tests/conftest.py)
- [backend/app/main.py](file://backend/app/main.py)
- [backend/app/database.py](file://backend/app/database.py)
- [backend/app/config.py](file://backend/app/config.py)
- [docker-compose.yml](file://docker-compose.yml)
- [tests/test_auth.py](file://tests/test_auth.py)
- [tests/test_queries.py](file://tests/test_queries.py)
- [tests/test_citations.py](file://tests/test_citations.py)
- [backend/app/api/deps.py](file://backend/app/api/deps.py)
- [backend/app/api/auth.py](file://backend/app/api/auth.py)
- [backend/app/api/queries.py](file://backend/app/api/queries.py)
- [backend/app/api/citations.py](file://backend/app/api/citations.py)
- [backend/app/workers/scheduler.py](file://backend/app/workers/scheduler.py)
- [backend/app/services/auth.py](file://backend/app/services/auth.py)
</cite>

## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖分析](#依赖分析)
7. [性能考虑](#性能考虑)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)

## 简介
本文件面向GEO项目的集成测试，系统性阐述端到端测试的实现方法与最佳实践，覆盖以下方面：
- FastAPI应用测试：通过ASGI传输层在内存中启动应用，使用异步HTTP客户端进行端到端请求验证。
- 数据库连接测试：基于异步SQLAlchemy引擎与会话管理，确保依赖注入与数据库交互正确。
- 外部服务集成测试：通过依赖注入覆盖与模拟（patch）实现对外部平台（如wenxin、kimi）的模拟调用。
- 测试环境配置：测试数据库、异步客户端、依赖注入覆盖与后台调度器的处理策略。
- 完整用户工作流：从认证到查询创建、执行到结果返回的端到端流程验证。
- 数据库事务与测试数据隔离：通过依赖注入覆盖与会话生命周期管理保障隔离性。
- 性能与负载测试：提供可扩展的测试方法与建议。

## 项目结构
GEO采用前后端分离架构，后端使用FastAPI + SQLAlchemy异步ORM，测试位于tests目录，通过pytest与pytest-asyncio驱动异步测试。数据库与缓存服务通过Docker Compose编排，便于本地与CI环境一致化。

```mermaid
graph TB
subgraph "测试环境"
TC["测试客户端<br/>AsyncClient(ASGI)"]
CFG["测试配置<br/>Settings(.env)"]
DC["Docker Compose<br/>db, redis, backend, frontend"]
end
subgraph "后端"
APP["FastAPI 应用<br/>app.main"]
DEPS["依赖注入<br/>api.deps"]
AUTH["认证路由<br/>api.auth"]
QUERIES["查询路由<br/>api.queries"]
CITATIONS["引用路由<br/>api.citations"]
SCHED["调度器<br/>workers.scheduler"]
DB["数据库引擎/会话<br/>database.py"]
end
DC --> APP
CFG --> APP
TC --> APP
APP --> AUTH
APP --> QUERIES
APP --> CITATIONS
APP --> SCHED
AUTH --> DB
QUERIES --> DB
CITATIONS --> DB
DEPS --> DB
```

图表来源
- [backend/app/main.py:1-48](file://backend/app/main.py#L1-L48)
- [backend/app/api/deps.py:1-43](file://backend/app/api/deps.py#L1-L43)
- [backend/app/api/auth.py:1-43](file://backend/app/api/auth.py#L1-L43)
- [backend/app/api/queries.py:1-86](file://backend/app/api/queries.py#L1-L86)
- [backend/app/api/citations.py:1-78](file://backend/app/api/citations.py#L1-L78)
- [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29)
- [backend/app/workers/scheduler.py:1-95](file://backend/app/workers/scheduler.py#L1-L95)
- [docker-compose.yml:1-71](file://docker-compose.yml#L1-L71)

章节来源
- [backend/app/main.py:1-48](file://backend/app/main.py#L1-L48)
- [docker-compose.yml:1-71](file://docker-compose.yml#L1-L71)

## 核心组件
- 异步HTTP客户端与ASGI传输层：通过ASGITransport在内存中启动FastAPI应用，避免真实网络开销，提升测试速度与稳定性。
- 依赖注入覆盖：使用app.dependency_overrides在测试中替换真实依赖（如认证用户），以模拟不同业务场景。
- 认证与令牌：通过create_access_token生成JWT，配合OAuth2PasswordBearer在路由中校验令牌。
- 数据库引擎与会话：异步SQLAlchemy引擎与会话工厂，确保测试中数据库交互的可控性与隔离性。
- 后台调度器：QueryScheduler负责周期性检查并触发查询任务，测试中通过mock屏蔽真实调度，防止后台任务干扰测试。

章节来源
- [tests/conftest.py:19-71](file://tests/conftest.py#L19-L71)
- [backend/app/api/deps.py:16-43](file://backend/app/api/deps.py#L16-L43)
- [backend/app/services/auth.py:24-34](file://backend/app/services/auth.py#L24-L34)
- [backend/app/database.py:6-29](file://backend/app/database.py#L6-L29)
- [backend/app/workers/scheduler.py:25-95](file://backend/app/workers/scheduler.py#L25-L95)

## 架构总览
下图展示测试视角下的端到端调用链路，从异步客户端发起请求，经由FastAPI路由、依赖注入、服务层，最终访问数据库或外部平台（通过模拟）。

```mermaid
sequenceDiagram
participant Test as "测试客户端"
participant App as "FastAPI 应用"
participant Dep as "依赖注入<br/>get_current_user"
participant Auth as "认证路由<br/>/api/v1/auth/*"
participant Queries as "查询路由<br/>/api/v1/queries/*"
participant Citations as "引用路由<br/>/api/v1/citations/*"
participant DB as "数据库引擎/会话"
Test->>App : "POST /api/v1/auth/register"
App->>Dep : "解析令牌/校验用户"
App->>Auth : "注册逻辑"
Auth->>DB : "写入用户"
DB-->>Auth : "提交成功"
Auth-->>Test : "201 用户信息"
Test->>App : "POST /api/v1/auth/login"
App->>Auth : "登录校验"
Auth-->>Test : "200 {access_token}"
Test->>App : "POST /api/v1/queries/"
App->>Dep : "校验令牌并解析用户"
App->>Queries : "创建查询"
Queries->>DB : "插入查询记录"
DB-->>Queries : "提交成功"
Queries-->>Test : "201 查询详情"
Test->>App : "GET /api/v1/citations/?query_id=..."
App->>Dep : "校验令牌并解析用户"
App->>Citations : "查询引用数据"
Citations->>DB : "读取引用记录"
DB-->>Citations : "返回数据"
Citations-->>Test : "200 引用列表"
```

图表来源
- [tests/test_auth.py:25-104](file://tests/test_auth.py#L25-L104)
- [tests/test_queries.py:29-154](file://tests/test_queries.py#L29-L154)
- [tests/test_citations.py:23-93](file://tests/test_citations.py#L23-L93)
- [backend/app/api/auth.py:13-43](file://backend/app/api/auth.py#L13-L43)
- [backend/app/api/queries.py:15-86](file://backend/app/api/queries.py#L15-L86)
- [backend/app/api/citations.py:25-78](file://backend/app/api/citations.py#L25-L78)
- [backend/app/api/deps.py:16-43](file://backend/app/api/deps.py#L16-L43)
- [backend/app/database.py:23-29](file://backend/app/database.py#L23-L29)

## 详细组件分析

### 测试环境与配置
- 测试数据库与外部服务：通过Docker Compose启动PostgreSQL与Redis，确保测试与生产环境一致；数据库URL与Redis URL在配置类中定义，便于在测试中覆盖。
- 异步客户端：使用ASGITransport在内存中启动FastAPI应用，避免网络抖动对测试的影响。
- 依赖注入覆盖：在conftest中定义override_get_current_user，使所有需要认证的路由在测试中自动获得模拟用户。
- 调度器屏蔽：通过mock_scheduler在测试期间禁用真实调度器，防止后台任务影响测试稳定性。

章节来源
- [docker-compose.yml:4-51](file://docker-compose.yml#L4-L51)
- [backend/app/config.py:7-14](file://backend/app/config.py#L7-L14)
- [tests/conftest.py:19-71](file://tests/conftest.py#L19-L71)

### 认证与用户工作流测试
- 注册与登录：通过patch模拟注册与登录服务，断言状态码与响应字段，确保认证流程正确。
- 当前用户信息：在依赖注入覆盖下，调用/me接口返回当前用户信息。
- 未认证访问：移除依赖注入覆盖后，访问受保护路由应返回401。

```mermaid
sequenceDiagram
participant C as "测试客户端"
participant A as "认证路由"
participant S as "认证服务"
participant D as "数据库"
C->>A : "POST /api/v1/auth/register"
A->>S : "register_user()"
S->>D : "查询邮箱是否存在"
S->>D : "插入新用户"
D-->>S : "提交成功"
S-->>A : "返回用户"
A-->>C : "201 Created"
C->>A : "POST /api/v1/auth/login"
A->>S : "authenticate_user()"
S->>D : "查询用户并校验密码"
D-->>S : "返回用户"
S-->>A : "生成JWT"
A-->>C : "200 {access_token}"
```

图表来源
- [tests/test_auth.py:25-104](file://tests/test_auth.py#L25-L104)
- [backend/app/api/auth.py:13-43](file://backend/app/api/auth.py#L13-L43)
- [backend/app/services/auth.py:37-69](file://backend/app/services/auth.py#L37-L69)

章节来源
- [tests/test_auth.py:25-104](file://tests/test_auth.py#L25-L104)
- [backend/app/api/auth.py:13-43](file://backend/app/api/auth.py#L13-L43)
- [backend/app/services/auth.py:37-69](file://backend/app/services/auth.py#L37-L69)

### 查询管理端到端测试
- 创建查询：在依赖注入覆盖与令牌头下，调用创建接口，断言返回字段与状态码。
- 列表与详情：通过patch模拟服务层返回值，断言分页与字段一致性。
- 更新与删除：断言更新后的字段与删除后的状态码。
- 权限限制：当超过配额时，断言403错误与错误信息。
- 资源不存在：断言404错误与错误信息。

```mermaid
sequenceDiagram
participant C as "测试客户端"
participant Q as "查询路由"
participant S as "查询服务"
participant D as "数据库"
C->>Q : "POST /api/v1/queries/"
Q->>S : "create_query()"
S->>D : "插入查询记录"
D-->>S : "提交成功"
S-->>Q : "返回查询"
Q-->>C : "201 Created"
C->>Q : "GET /api/v1/queries/?skip=&limit="
Q->>S : "get_queries()"
S->>D : "查询记录"
D-->>S : "返回列表"
S-->>Q : "返回分页"
Q-->>C : "200 OK"
C->>Q : "PUT /api/v1/queries/{id}"
Q->>S : "update_query()"
S->>D : "更新记录"
D-->>S : "提交成功"
S-->>Q : "返回更新后记录"
Q-->>C : "200 OK"
C->>Q : "DELETE /api/v1/queries/{id}"
Q->>S : "delete_query()"
S->>D : "删除记录"
D-->>S : "提交成功"
S-->>Q : "返回True"
Q-->>C : "204 No Content"
```

图表来源
- [tests/test_queries.py:29-154](file://tests/test_queries.py#L29-L154)
- [backend/app/api/queries.py:15-86](file://backend/app/api/queries.py#L15-L86)

章节来源
- [tests/test_queries.py:29-154](file://tests/test_queries.py#L29-L154)
- [backend/app/api/queries.py:15-86](file://backend/app/api/queries.py#L15-L86)

### 引用数据与统计导出测试
- 引用列表：断言分页、字段与过滤参数生效。
- 统计信息：断言总量、引用率、按平台分布与趋势数据。
- CSV导出：断言内容类型、附件头与CSV内容片段。

```mermaid
sequenceDiagram
participant C as "测试客户端"
participant R as "引用路由"
participant RS as "引用服务"
participant D as "数据库"
C->>R : "GET /api/v1/citations/?query_id=&platform=&start_date=&end_date=&skip=&limit="
R->>RS : "get_citations()"
RS->>D : "查询引用记录"
D-->>RS : "返回列表"
RS-->>R : "返回分页"
R-->>C : "200 OK"
C->>R : "GET /api/v1/citations/stats?query_id="
R->>RS : "get_citation_stats()"
RS->>D : "聚合统计"
D-->>RS : "返回统计"
RS-->>R : "返回统计"
R-->>C : "200 OK"
C->>R : "GET /api/v1/reports/export/csv?query_id="
R->>RS : "export_citations_csv()"
RS-->>R : "返回CSV内容"
R-->>C : "200 OK, text/csv, attachment"
```

图表来源
- [tests/test_citations.py:23-93](file://tests/test_citations.py#L23-L93)
- [backend/app/api/citations.py:25-78](file://backend/app/api/citations.py#L25-L78)

章节来源
- [tests/test_citations.py:23-93](file://tests/test_citations.py#L23-L93)
- [backend/app/api/citations.py:25-78](file://backend/app/api/citations.py#L25-L78)

### 数据库事务管理与测试数据隔离
- 会话生命周期：get_db提供异步会话生成与关闭，确保每次请求在独立会话中执行，避免跨请求污染。
- 依赖注入覆盖：通过app.dependency_overrides在测试中替换get_current_user，保证路由依赖始终可用且可控。
- 事务隔离：测试中通过patch模拟服务层，不直接写入真实数据；若需真实写入，应在测试事务中回滚或使用独立测试库。

```mermaid
flowchart TD
Start(["测试开始"]) --> Override["依赖注入覆盖<br/>get_current_user"]
Override --> Session["获取异步会话<br/>get_db()"]
Session --> Exec["执行路由/服务逻辑"]
Exec --> Commit{"提交/回滚?"}
Commit --> |提交| Close["关闭会话"]
Commit --> |回滚| Close
Close --> End(["测试结束"])
```

图表来源
- [tests/conftest.py:42-50](file://tests/conftest.py#L42-L50)
- [backend/app/database.py:23-29](file://backend/app/database.py#L23-L29)

章节来源
- [tests/conftest.py:42-50](file://tests/conftest.py#L42-L50)
- [backend/app/database.py:23-29](file://backend/app/database.py#L23-L29)

### 外部服务集成测试
- 平台模拟：通过patch将平台调用替换为模拟实现，断言触发查询任务与返回的任务信息。
- 调度器屏蔽：在测试期间mock调度器，避免真实后台任务执行，确保测试确定性。

章节来源
- [tests/test_citations.py:75-93](file://tests/test_citations.py#L75-L93)
- [tests/conftest.py:19-26](file://tests/conftest.py#L19-L26)

## 依赖分析
- 应用生命周期：FastAPI应用在lifespan中启动调度器，并在关闭时优雅shutdown。
- 路由依赖：认证与查询/引用路由均依赖get_current_user与get_db，形成清晰的依赖链。
- 服务层：认证、查询、引用服务分别封装业务逻辑，便于在测试中通过patch进行替换。

```mermaid
graph LR
APP["FastAPI 应用"] --> LIFE["lifespan 启停调度器"]
APP --> AUTH["认证路由"]
APP --> QUERIES["查询路由"]
APP --> CITATIONS["引用路由"]
AUTH --> DEPS["get_current_user"]
QUERIES --> DEPS
CITATIONS --> DEPS
DEPS --> DB["get_db/AsyncSession"]
```

图表来源
- [backend/app/main.py:13-22](file://backend/app/main.py#L13-L22)
- [backend/app/api/deps.py:16-43](file://backend/app/api/deps.py#L16-L43)
- [backend/app/database.py:23-29](file://backend/app/database.py#L23-L29)

章节来源
- [backend/app/main.py:13-22](file://backend/app/main.py#L13-L22)
- [backend/app/api/deps.py:16-43](file://backend/app/api/deps.py#L16-L43)
- [backend/app/database.py:23-29](file://backend/app/database.py#L23-L29)

## 性能考虑
- 内存测试：使用ASGI传输层与异步客户端，避免网络开销，提升测试吞吐量。
- 调度器控制：在测试中禁用真实调度器，减少后台任务对测试性能的影响。
- 数据库隔离：通过独立测试库或事务回滚策略，避免并发测试导致的数据竞争。
- 负载测试建议：可在现有测试基础上扩展压力测试脚本，结合异步客户端批量发送请求，监控响应时间与错误率；注意在测试环境中使用独立数据库实例以避免影响生产数据。

## 故障排查指南
- 401未认证：确认测试中是否正确设置依赖注入覆盖与Authorization头。
- 403权限不足：检查配额限制逻辑与用户计划，确保测试数据符合预期。
- 404资源不存在：确认查询ID与用户归属，确保服务层返回None时路由抛出404。
- 调度器干扰：若出现不可预期的后台任务行为，确认是否启用了mock_scheduler。

章节来源
- [tests/test_auth.py:88-104](file://tests/test_auth.py#L88-L104)
- [tests/test_queries.py:50-71](file://tests/test_queries.py#L50-L71)
- [tests/test_queries.py:127-154](file://tests/test_queries.py#L127-L154)
- [tests/conftest.py:19-26](file://tests/conftest.py#L19-L26)

## 结论
本文档提供了GEO项目集成测试的完整方法论与实施细节，涵盖FastAPI应用测试、数据库连接、外部服务模拟、端到端用户工作流验证、事务与隔离策略以及性能与负载测试建议。通过依赖注入覆盖与异步客户端，测试具备高可靠性与可维护性；借助Docker Compose与配置类，测试环境与生产环境保持一致，便于持续集成与部署。

## 附录
- 建议在CI中增加：
  - 数据库迁移与初始化脚本的集成测试。
  - Redis健康检查与连接超时重试策略验证。
  - 前后端联调测试，确保API与前端交互稳定。