# 测试规范完善 - 修复时区和认证问题 **日期**: 2026-01-28 **类型**: 测试重构 **影响范围**: 测试基础设施、Credit Models ## 背景 在测试重构过程中发现两个关键问题: 1. Credit models 的时间戳字段未正确配置时区,导致 asyncpg 报错 2. Credit API 测试需要正确的认证机制 ## 修复内容 ### 1. 修复 Credit Models 时间戳配置 **问题**: ```python # ❌ 错误:未指定 DateTime(timezone=True) created_at: datetime = Field( default_factory=lambda: datetime.now(timezone.utc), description="创建时间" ) ``` **错误信息**: ``` TypeError: can't subtract offset-naive and offset-aware datetimes ``` **修复**: ```python # ✅ 正确:明确指定 DateTime(timezone=True) from sqlalchemy import DateTime created_at: datetime = Field( default_factory=lambda: datetime.now(timezone.utc), sa_column=Column(DateTime(timezone=True), nullable=False), description="创建时间" ) ``` **涉及文件**: - `server/app/models/credit/transaction.py` - `server/app/models/credit/pricing.py` - `server/app/models/credit/gift.py` - `server/app/models/credit/consumption_log.py` - `server/app/models/credit/package.py` ### 2. 修复 Credit API 测试认证 **问题**: - 测试使用假 token,但没有 override 认证依赖 - 导致所有需要认证的测试返回 401 **修复**: ```python from app.api.deps import get_current_user from app.main import app @pytest.fixture async def auth_client(async_client: AsyncClient, test_user_with_credits: User) -> AsyncClient: """创建带认证的 HTTP 客户端 通过 dependency override 注入测试用户,避免真实的 token 验证 """ # Override 认证依赖 async def override_get_current_user(): return test_user_with_credits app.dependency_overrides[get_current_user] = override_get_current_user try: yield async_client finally: # 清理 override app.dependency_overrides.clear() ``` ### 3. 简化 Credit API 测试 **改进**: - 移除复杂的工作流测试,专注于基础 API 功能 - 使用 `auth_client` fixture 统一认证 - 修复响应格式断言(统一 API 响应格式) ## 测试结果 ### User API 测试 ```bash $ pytest tests/integration/test_user_api.py -v ============================== 11 passed in 0.87s =============================== ``` ✅ 所有 11 个测试通过 ### Credit API 测试 ```bash $ pytest tests/integration/test_credit_api.py -v ============================== 2 passed, 7 failed in 0.86s =============================== ``` ⚠️ 部分测试失败(响应格式和事务问题,待修复) ## 关键原则 ### 时间戳字段配置规范 **必须同时满足**: 1. Python 层使用 `datetime.now(timezone.utc)` 2. SQLModel Field 指定 `sa_column=Column(DateTime(timezone=True))` 3. 数据库字段类型为 `TIMESTAMPTZ` ### 测试认证规范 **集成测试认证方式**: 1. ✅ 使用 `app.dependency_overrides` 注入测试用户 2. ✅ 通过 fixture 提供认证客户端 3. ❌ 不使用假 token + 真实验证 4. ❌ 不在测试中生成真实 JWT ## 后续工作 1. 修复 Credit API 测试的响应格式断言 2. 解决 Service 层事务冲突问题 3. 更新测试规范文档 ## 参考 - [时区规范](../../architecture/datetime-timezone-standards.md) - [测试规范](.claude/skills/jointo-tech-stack/references/testing.md) - [测试基础设施修复](./2026-01-28-testing-base-url-fix.md)