Expedia Group开源了mockql-rs,一个Rust CLI工具,能在请求时用LLM生成的数据填充被@mock注解标注的GraphQL字段。这是过去六个月内第三次公开尝试解决同一类问题,前两次分别是Airbnb在4月推出的@generateMock指令,以及2月开放的GraphQL基金会RFC。
三种方案采用了显著不同的设计,其中两种使用相同的指令名称但含义并不相同。它们的共同前提是GraphQL选择集已经是一个规范。Expedia Group的软件工程师Samuel Vazquez指出了这种方法的吸引力:它颠覆了生成工具的常见失败模式,模型不擅长创造形状,但擅长填充形状,而schema为它们免费提供了一个界限明确的形状。
开发者不再需要手工输入两百行的JSON固件文件
如果第二天早上schema发生了变更,那个手工维护的固件文件就会失效。mockql-rs作为独立进程位于客户端和服务器之间。开发者使用@mock注解标注字段以及可选的提示,该工具使用apollo-compiler解析并验证针对schema的操作,将被注解标注的字段与真实字段分离,将真实字段转发到上游,使用该操作和子集schema提示模型,然后将两者合并为一个响应。
实际结果是单个响应可以同时包含来自真实后端的数据和来自尚未实现的字段解析器的生成数据。Expedia选择CLI的理由是任何测试运行器、CI任务或构建脚本都可以执行进程,避免了SDK或客户端库依赖。
一个响应里,真实数据和生成数据平起平坐
查询仅注解标注尚未准备好的字段。在一个TripDetails查询示例中,property字段由上游解析,recommendations字段带有@mock注解和提示“5 most popular nearby restaurants”,由模型在该上下文中生成。响应结合两个来源:酒店名称和地址来自后端;餐厅名称、描述和距离是模型输出。
两者在同一个有效负载中都具有相等的权威性,响应中没有任何内容标识它们的差异。Airbnb的方法在4月发布,改为在构建时运行。它的@generateMock指令在Niobe代码生成期间进行处理,同时发出模拟数据的JSON文件和类型化的访问函数供演示应用、快照测试和单元测试使用,生成器在后续运行中有意保留了工程师的手动编辑能力。
RFC走了第三条路,而且步子更谨慎
RFC采取了第三种立场。它在操作而不是字段上定义@mock,使用名称参数在命名响应之间进行选择,并要求符合规范的客户端返回模拟数据而无需发出任何网络请求。模拟响应位于与源文件相邻的graphql_mocks目录中,以操作来进行命名,带有保留的default键和在重新生成时使用的可选描述。LLM生成仅作为推荐策略出现,而不是作为一种机制。
这种差异不仅仅是语法上的差异。RFC要求客户端检测模拟响应何时对其操作的有效性已经产生了漂移,并强制进行纠正措施,并声明模拟必须作为应用程序测试套件的一部分进行验证。Expedia的生成数据在每次运行时生成,这提供了上下文一致性但不能提供快照测试所依赖的可重复性。两篇文章都没有解决非确定性装置对CI意味着什么的问题。
智能体工作流已经被提前写进草案
RFC还直接预料到了智能体工作流的场景,建议实现者提供一个Agent Skill,以便编码智能体可以对话式地添加或修改模拟变体,文档中包含建议的SKILL.md。这样就能将模拟管理置于智能体被教授操作的其他代码库约定旁边。
对于要权衡采用的团队,需要注意这些标准目前所处的位置。RFC仍处于第0阶段,被描述为初步草案,没有列出倡导者,这是GraphQL规范过程中最早的阶段,不能保证它的进展。Expedia的实现已经在指令放置、参数名称和网络行为上与其产生了差异。所以,如果今天有团队把@mock作为标准来推行,实际上只是把某一家供应商对这个名称的理解当成了标准,只不过这个名称在规范草案中也有提及。
为什么是GraphQL,而不是REST
更值得关注的是,这种模式为何在GraphQL而不是REST中出现。与Schema形状一致的输出,是让生成的数据变得真正可用、而不只是“看起来像那么回事的乱码”的关键约束。同时,也正是基于此,工具才能够检测生成的数据何时不再匹配查询。至于它最终是会成为一个正式的规范,还是沦为三个互不兼容的实现,目前还是个未知数。
热门跟贴