testclient发cookie需用httpx.cookies().set()而非字典;user-agent须按请求传headers;不可await client.get();不触发startup/shutdown事件,需手动调用或抽离初始化逻辑。

TestClient 怎么发带 Cookie 的请求
直接传 cookies 参数就行,但别用字典——TestClient 内部用的是 httpx.Cookies 对象,字典会静默失效。
- 正确做法:先创建
httpx.Cookies()实例,再用.set()添加,最后传给client.get(..., cookies=...) - 常见错误现象:
client.get("/api", cookies={"session_id": "abc"})看似正常,但服务端收不到Cookie头 - 注意路径和域名:测试时默认域是
testserver,如果代码里写了domain="example.com",这个 Cookie 会被丢弃
如何让 TestClient 模拟真实浏览器的 User-Agent
TestClient 默认不带 User-Agent,某些中间件或路由逻辑(比如移动端重定向)会因此跳过或报错。
- 必须显式传
headers:比如client.get("/page", headers={"User-Agent": "Mozilla/5.0 (X11; Linux x86_64)"}) - 别写在
client初始化里——那会全局污染,影响其他测试;每个请求按需覆盖更安全 - 如果用
pytest+fixture封装,记得每次新建headers字典,避免键值被意外复用
TestClient 调用异步 endpoint 却卡住?
不是 bug,是没配对——TestClient 本身是同步的,它调用异步路由时,底层靠 anyio 或 asyncio.run() 同步阻塞执行。但如果你在测试里混用了 await,就会死锁。
- 绝对不要在测试函数里写
await client.get(...):这是错的,client.get返回的是Response,不是协程 - 真正要测异步逻辑?用
httpx.AsyncClient配app.router测试,或者直接单元测 handler 函数本身 - 性能影响:每次
client.get调用都会启停事件循环,高频测试(比如参数化)可能变慢,可考虑批量断言而非拆成多个请求
为什么 TestClient 不触发 startup/shutdown 事件
因为默认不启动完整生命周期——它只挂载了 app 的路由层,绕过了 lifespan 管理器。
立即学习“Python免费学习笔记(深入)”;
- 想跑
@app.on_event("startup")?得用TestClient(app, raise_server_exceptions=False)+ 手动调用app.router.lifespan.startup()(不推荐) - 更稳妥的做法:把数据库连接、缓存初始化等逻辑抽成函数,在测试 setup 阶段显式调用,而不是依赖 lifespan
- 容易被忽略的点:有些 ORM(如 SQLAlchemy 2.0+)的 async session factory 必须在事件循环内初始化,
TestClient里直接 import 可能报RuntimeError: There is no current event loop










