FastAPI/SQLModel集成测试:不使用freezegun的时间冻结方案,及freezegun测试登录日志时间不一致问题求助
FastAPI/SQLModel集成测试:不使用freezegun的时间冻结方案,及freezegun测试登录日志时间不一致问题求助
大家好,我最近在用pytest给FastAPI+SQLModel的应用写集成测试,想在应用内部直接冻结时间。freezegun在单元测试场景下用着没问题,但在运行中的FastAPI应用里就不太靠谱了,遇到了一个奇怪的时间不一致问题,想请教下大家怎么解决,或者有没有不用freezegun的替代方案?
问题场景与测试代码
我用了pytest-freezegun插件,测试代码如下:
@pytest.mark.asyncio async def test_login__authorize__check_log_date(session, freezer): # Arrange await push_one_user() payload = {USERNAME_KEY: USER_LOGIN, PASSWORD_KEY: PLAIN_PASSWORD} # Act await execute_post_request("/auth/login", payload=payload) # Assert last_log = (await get_user_log(session)).pop() assert last_log.date_connexion == datetime.now()
测试结果
运行后断言失败,两个FakeDatetime时间对不上:
Expected :FakeDatetime(2025, 7, 29, 7, 19, 16, 33142) Actual :FakeDatetime(2025, 7, 29, 9, 19, 16, 133177)
奇怪的是,我在代码里用的是不带时区的datetime.now(),按道理应该被freezegun统一替换才对,但结果却差了两个小时左右?
相关服务端代码
AuthService中的认证逻辑
class AuthService: @classmethod async def authenticate_user( cls, session: SessionDep, username: str, password: str, ) -> Optional[User]: user = await UserService.get_user_by_login_with_validity_check( session, username ) if not user: raise CREDENTIALS_EXCEPTION is_correct_password = await PasswordService.verify_password( password, user.hashed_password ) if is_correct_password is not True: raise CREDENTIALS_EXCEPTION user.set_last_login_date() # 怀疑问题出在这个LoginLog实例化环节 login_log = LoginLog(user=user) session.add(login_log) await session.commit() return user
LoginLog模型定义
class LoginLog(SQLModel, table=True): __tablename__ = "login_log" id: Optional[int] = Field(default=None, primary_key=True) # 重点怀疑这个default_factory的执行时机 date_connexion: datetime = Field(default_factory=datetime.now) id_user: uuid.UUID = Field(foreign_key="user.id") # Relations user: "User" = Relationship(back_populates="connexions")
我现在的疑惑是:明明测试和应用代码里都用了datetime.now(),freezegun应该把所有datetime.now()的调用都替换成冻结的时间才对,但为什么LoginLog里生成的时间和测试里取的datetime.now()会不一样?是不是SQLModel的default_factory在session提交的时候才会执行?或者是异步场景下freezegun的事件循环兼容问题?
另外,如果freezegun在这种集成测试场景下不好用,有没有其他方案可以在FastAPI应用中可靠地冻结内部时间?
内容来源于stack exchange
相关产品推荐
相关产品推荐

