You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

3.5 KiB

测试规范完善 - 修复时区和认证问题

日期: 2026-01-28
类型: 测试重构
影响范围: 测试基础设施、Credit Models

背景

在测试重构过程中发现两个关键问题:

  1. Credit models 的时间戳字段未正确配置时区,导致 asyncpg 报错
  2. Credit API 测试需要正确的认证机制

修复内容

1. 修复 Credit Models 时间戳配置

问题

# ❌ 错误:未指定 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

修复

# ✅ 正确:明确指定 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

修复

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 测试

$ pytest tests/integration/test_user_api.py -v
============================== 11 passed in 0.87s ===============================

所有 11 个测试通过

Credit API 测试

$ 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. 更新测试规范文档

参考