
Keploy 严格模式下预编译语句重放失败怎么排查【免费下载链接】keployOpen-source platform for creating safe, isolated production sandboxes for API, integration, and E2E testing.项目地址: https://gitcode.com/GitHub_Trending/ke/keploy应用使用 MySQL 预编译语句或 Postgres 扩展查询协议prepared statements时keploy test重放经常会在严格窗口strict-window模式下失败录制时PREPARE/Parse帧被某个测试的 mock 池消费掉后续测试在同一连接上按语句 id 执行execute时找不到对应的 mock。docs/explanation/mock-lifetimes.md 的 Troubleshooting 一节直接给出了这条故障的排查路径本文按该文档组织成可执行的排查步骤。先理解严格模式为什么会影响预编译语句Keploy 的每个 mock 都有一个 lifetime决定了重放匹配器认为它多久有效LifetimeYAML 标签spec.metadata.type是否匹配后消费是否受时间窗口过滤典型内容Sessionconfig否跨测试可复用否HTTP 认证刷新、MySQL 握手、PostgresSET/SHOWConnectionconnection否仅在同一connID内可复用否PostgresParse预编译语句注册、MySQLCOM_STMT_PREPAREPer-test其他任意标签常见mocks、HTTP_CLIENT或空是匹配后从池中删除是严格窗口下数据查询、HTTP 出站请求、Bind/Execute严格模式下per-test mock 会做时间窗口过滤窗口是外层 HTTP/gRPC 测试的[test-request-timestamp, test-response-timestamp]区间mock 自身请求时间戳落在窗口外就被丢弃这是防止跨测试串扰cross-test bleed的机制。Session 和 Connection 两种生命周期的 mock 不会被窗口检查丢弃。预编译语句的故障就出在这里测试 A 的连接执行PREPARE ... AS ...测试 B 在同一连接上按 id 引用该语句。如果PREPARE帧被标成 per-test严格的 per-test 窗口会把它从测试 A 的池中丢掉测试 B 的execute随即失败。正确的录制会把Parse/COM_STMT_PREPARE帧标为type: connection让语句注册只在拥有它的connID内可复用既解决重放又不引入串扰。严格模式的开关及默认值# keploy.yaml test: strictMockWindow: true # cross-test bleed prevention或环境变量KEPLOY_STRICT_MOCK_WINDOW1 keploy test -c ...文档说明当前默认就是true。环境变量与配置的关系是启用值强制打开显式禁用值0无论配置如何都强制关闭。严格模式激活时每个 agent 进程会输出一条一次性 Info 日志同时指明两种关闭方式config 与 env 各是什么排查时可以直接从日志确认当前生效状态。排查步骤1. 打开 mock 文件检查 PREPARE/Parse 帧的标签打开对应测试集的mocks.yaml找到 MySQLCOM_STMT_PREPARE或 PostgresParse的 mock看spec.metadata.typeversion: api.keploy.io/v1beta1 kind: PostgresV2 name: connection spec: metadata: type: connection # ← connection-scoped; reusable within connID connID: conn-17 requestOperation: Parse query: SELECT id FROM users WHERE email $1 # ... the ParseComplete response以上为文档示例输出实际字段值以你的录制为准。判断标准type: connection且connID非空 → 标签正确问题不在这一步继续第 2 步缺少type: connection没有该字段或值不是connection→ 录制早于标签约定PREPARE 帧被当作 per-test 处理直接走「修复路径」一节。注意一个边界connectionmock 缺少connID时会退化为 session 生命周期而不是被 per-test 消费以避免消费掉配对的 execute但正常的type: connection条目必须带非空connID。另外Postgres v2 中空查询的Parse驱动 PS-cache 探测属于 session 分类非空Parse才属于 connection 分类——检查时按 query 是否为空区分不要指望空Parse带type: connection。2. 确认录制没有依赖 legacy kind 回退旧录制在没有任何type标签时DeriveLifetime会按 kind 推断回退到 session。这个回退是静默的不会逐条打日志但会被计数agent 在重放完成摘要replay-completion summary中输出 legacy kind fallback fires 计数。计数为 0 → 录制不依赖回退跳过这一步计数非 0 → 说明至少有这么多 mock 没有带metadata.type标签是按旧 kind 开关分类的。重放仍然能工作但要让计数归零需用当前版本的 keploy 重新录制。修复路径文档给出两条按情况二选一用当前版本的 keploy 重新录制让Parse/COM_STMT_PREPARE帧在捕获时就被打上type: connection标签。这是根治方式LifetimeConnection已接入 MySQL 和 Postgres 两个 matcher只要录制包含带稳定connID的 Parse/COM_STMT_PREPARE 帧严格模式下 PREPARE/execute 的关联就能正常工作。临时关闭严格模式适用于还在使用旧录制的过渡期# keploy.yaml test: strictMockWindow: falseKEPLOY_STRICT_MOCK_WINDOW0 keploy test -c ...关闭严格模式是为依赖旧式宽松行为的旧录制准备的文档原文如此表述。副作用是失去跨测试串扰防护所以应作为过渡手段而非默认配置。验证修复结果重放后回到两处检查mocks.yaml中 PREPARE/Parse mock 的spec.metadata.type为connection且connID与同一连接上其他 mock 的connID一致。ConnectionID必须在单个会话的所有 mock 间保持稳定来源是 V2 架构下的supervisor.Session.ClientConnID连接级状态预编译语句依赖这个标签做匹配——docs/reference/mock-matcher-contract.md 明确列出缺失ConnectionID时连接级状态无法匹配重放会静默产生错误结果所以这一步不能只看测试通过要核对标签本身。重放完成摘要中 legacy kind fallback fires 计数为 0说明录制已不再依赖未打标签的旧分类路径。两个相邻现象的区分排查时容易混淆的两个信号文档也一并给出了判断依据HTTP mock 被意外消费预期可复用却被消费同样先查spec.metadata.type缺失即默认 per-test。如果认为它该是 session 级例如长生命周期的认证刷新要么升级 keploy该场景的分类可能在新版本已支持要么携带 mock 的请求行和请求头信息向 keploy 仓库提交 issue。摘要中出现[session mock] hit count 0表示某个 session mock 在整个测试运行中从未被匹配通常是录制捕获了应用已不再发起的一次性调用一般可以不带它重新录制如果该调用是条件性的只在特定输入下出现则保留。注意文档的限定在全部 parser 完成迁移前session mock 的 0 计数既可能是从未使用也可能是被使用了但所属 parser 尚未迁移此时不能直接据此删除 mock。相关文档docs/explanation/mock-lifetimes.md — 三种 mock 生命周期、严格窗口机制与 Troubleshooting 原文docs/reference/mock-matcher-contract.md — 匹配器读取的字段契约含connID、时间戳与Kind的不变量及违反后果生命周期内部实现在 pkg/models/lifetime.go。【免费下载链接】keployOpen-source platform for creating safe, isolated production sandboxes for API, integration, and E2E testing.项目地址: https://gitcode.com/GitHub_Trending/ke/keploy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考