FastAPI WebSocket 自动化测试实战:用 TestClient 与 websocket_connect 编写端到端用例
FastAPI WebSocket 自动化测试实战用 TestClient 与 websocket_connect 编写端到端用例【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapiWebSocket 是 FastAPI 提供实时双向通信能力的关键通道而基于同一套TestClient就能够在不启动真实服务器的情况下对其做端到端测试。本文以官方文档“Testando WebSockets测试 WebSockets”为核心骨架结合仓库内的示例源码与测试用例系统讲解如何在 FastAPI 项目中用client.websocket_connect()编写可复现、可断言的 WebSocket 测试。读完本文你将掌握在同一个TestClient内同时测试普通 HTTP 接口与 WebSocket 端点的方法receive_json()/send_json()等收发 API 的使用WebSocket 会话中查询参数、依赖与断开连接的测试要点以及这些能力在仓库源码与 pytest 用例中的真实落点。一个 TestClient两种协议为什么测试 WebSocket 不需要另起炉灶FastAPI 的测试体系建立在 fastapi/testclient.py 之上而该文件仅做了一件事——直接再导出 Starlette 的TestClientfrom starlette.testclient import TestClient as TestClient # noqa这意味着 HTTP 接口测试与 WebSocket 测试天然共享同一套客户端基础设施同一个TestClient(app)实例既可以发起client.get()也可以通过client.websocket_connect()建立 WebSocket 会话。测试库不必启动真实网络端口即可让请求完整穿过路由、依赖注入与应用代码因而对端到端行为有很高的保真度。官方文档 docs/pt/docs/advanced/testing-websockets.md 开篇即点明核心思想你可以用同一个TestClient来测试 WebSockets。为此需要在一个with语句中使用TestClient连接 WebSocket。其中的代码块来自仓库示例 docs_src/app_testing/tutorial002_py310.py文档用hl[27:31]专门高亮了核心的test_websocket函数。完整示例拆解HTTP 与 WebSocket 用例同文件共存示例应用在同一个文件里定义了一个普通 HTTP 端点与一个 WebSocket 端点from fastapi import FastAPI from fastapi.testclient import TestClient from fastapi.websockets import WebSocket app FastAPI() app.get(/) async def read_main(): return {msg: Hello World} app.websocket(/ws) async def websocket(websocket: WebSocket): await websocket.accept() await websocket.send_json({msg: Hello WebSocket}) await websocket.close() def test_read_main(): client TestClient(app) response client.get(/) assert response.status_code 200 assert response.json() {msg: Hello World} def test_websocket(): client TestClient(app) with client.websocket_connect(/ws) as websocket: data websocket.receive_json() assert data {msg: Hello WebSocket}逐段来看这条 WebSocket 链路服务端路由app.websocket(/ws)声明 WebSocket 端点处理函数收到 WebSocket 实例后先await websocket.accept()完成握手再send_json()发送一条 JSON 消息最后close()主动关闭连接。这段逻辑与 docs/pt/docs/advanced/websockets.md 中介绍的服务端收发流程完全一致。客户端建立会话client.websocket_connect(/ws)返回一个 WebSocket 测试会话with语句在退出代码块时负责自动完成会话收尾与连接关闭这与 HTTP 测试中TestClient作为上下文管理器使用如触发事件的思路一脉相承。服务端“先发、客户端后收”本示例中服务端accept()后立刻推送了一条 JSON因此客户端进入with块后直接receive_json()即可取回并用assert校验内容与结构。注意两者顺序是异步配合的——receive_json()会阻塞等待直到服务端发出消息测试因此天然具备同步化的“握手—发送—接收—断言”节奏。会话对象复用为收发句柄with ... as websocket暴露出的对象与普通 HTTP 响应的用法不同它本身就是收发消息的通道支持receive_json()/receive_text()以及反向的send_json()/send_text()。连接参数的传递URL 路径与查询字符串websocket_connect()接受的路径与普通请求相同因此在测试中不仅能命中形如/ws的固定路径还能携带路径参数与查询参数。仓库中 WebSocket 教程的测试用例 tests/test_tutorial/test_websockets/test_tutorial002.py 就展示了带路径和查询串的连接方式例如with client.websocket_connect(/items/bar/ws?tokensome-token) as websocket: ...这条连接串同时验证了两件事路径参数/items/bar/ws中的bar可被路由解析查询参数tokensome-token这类参数能够进入 WebSocket 端点的依赖系统。这一点在真实项目中非常实用——许多 WebSocket 端点会通过查询参数传递鉴权令牌或房间号参见 docs/pt/docs/advanced/websockets.md 中“使用Depends和其他”一节WebSocket 端点同样支持Depends并可用WebSocketException表达握手期的错误。于是测试可以针对“合法令牌能建连、非法令牌被拒绝”这类安全场景编写多条用例唯一区别只是websocket_connect()的 URL 参数不同。在测试中模拟服务端收发与断开把示例进一步泛化一个典型的“回声”型 WebSocket 端点在测试里大致对应这样的交互节奏服务端先accept()随后循环receive_text()/send_text()def test_echo(): client TestClient(app) with client.websocket_connect(/echo) as websocket: websocket.send_text(hello) data websocket.receive_text() assert data hello需要注意的边界行为断开语义当对端关闭连接后服务端一侧的receive_text()/receive_json()会抛出WebSocketDisconnect异常。官方文档在 docs/pt/docs/advanced/websockets.md 的“处理断开与多客户端”一节明确指出应捕获该异常来清理房间成员、资源等状态。因此为“客户端中途掉线”场景编写测试时可以通过退出with上下文或调用websocket.close()触发服务端的异常分支再用pytest.raises断言其被正确捕获。消息乱序/粘包WebSocket 测试会话与生产连接遵循相同的消息边界测试里收发顺序必须与服务端的推送节奏严格对应这正是用真实客户端驱动的好处——能暴露“服务端没发、客户端先等”的逻辑错误。多次收发一个with块内可反复调用receive_*/send_*用于断言连续多条消息如状态推送、房间广播的序列与内容。从文档到仓库这段示例的工程化落地示例并非孤立代码它在仓库中构成了完整的“编写—入库—执行”闭环可运行示例docs_src/app_testing/tutorial002_py310.py 即葡萄牙语文档{* ../../docs_src/app_testing/tutorial002_py310.py *}指令引用的真实源文件代码可直接被 mkdocs 渲染进页面pytest 覆盖tests/test_tutorial/test_testing/test_tutorial002.py 从该示例模块导入test_read_main与test_websocket并在主测试进程中执行保证“文档示例”与“回归测试”永不脱节from docs_src.app_testing.tutorial002_py310 import test_read_main, test_websocket def test_main(): test_read_main() def test_ws(): test_websocket()同一约定贯穿全仓库带路径/查询参数连接、依赖校验、断开异常等进阶模式均在 tests/test_tutorial/test_websockets/ 下的教程测试中有对应实现。撰写自己的 WebSocket 测试时完全可以参照test_tutorial002的分层方式——端点逻辑放docs_src示例、测试放tests/test_tutorial、由薄封装测试统一驱动。运行与接入 CI 的实践要点在仓库根目录执行以下命令即可单独验证本文的示例用例pytest tests/test_tutorial/test_testing/test_tutorial002.py若要连同全部 WebSocket 教程用例一起回归可执行pytest tests/test_tutorial/test_websockets/实践中的几条经验总结始终用with管理会话让上下文管理器负责关闭连接避免测试泄漏未释放的 WebSocket 会话按“服务端消息节奏”组织断言先明确端点accept()后是主动推送还是等待客户端消息再决定测试里先receive_*还是先send_*把鉴权参数放进 URL令牌、房间号等通过查询字符串注入复用服务端既有的Depends校验逻辑做正反用例把文档示例与测试对齐像 docs_src/app_testing/tutorial002_py310.py 那样让示例代码同时被文档渲染与 pytest 引用是最省心的防漂移手段。小结WebSocket 测试并不需要独立的测试框架——借助 FastAPI 直接暴露的TestClient只需把websocket_connect(/ws)放进with语句即可对握手、收发、鉴权与断连做完整的端到端断言。官方文档 docs/pt/docs/advanced/testing-websockets.md 给出的正是这一最小可用范式而其背后的完整链路——示例源码、pytest 驱动与 Starlette 客户端再导出——都在当前仓库中真实可查。掌握这一模式后为实时聊天、推送通知、协作编辑等任何 WebSocket 功能补齐自动化测试都只是把路由换成你自己的端点那么简单。【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考