You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么Rspec中调用.order("created_at DESC")会导致allow存根失效?

Rspec中order查询后方法存根失效的原因

这个问题的核心是Rspec方法存根的绑定规则和ActiveRecord查询的对象实例特性两者的差异:

  • Rspec的allow(object).to receive方法存根是绑定在内存中单个特定实例上的,仅对当前绑定的对象生效,不会作用到其他哪怕属性、id完全相同的同类型实例上。
  • ActiveRecord的等值判断eq默认只对比类名和主键id,只要是同表同id的记录,哪怕是内存中两个完全独立的实例,eq判断都会返回true。
  • 你调用book.pages.first时,由于之前执行过book.pages << page,关联的内存缓存已经加载,Rails不会触发数据库查询,直接返回你之前打了存根的page实例,因此存根生效。
  • 你调用book.pages.order("created_at DESC").first时,order条件触发了新的数据库查询,Rails会用查询到的记录重新初始化一个全新的Page实例,这个新实例和你之前打存根的page虽然id相同、eq判断相等,但属于内存中完全独立的两个对象,存根自然不会生效。

常见解决方案

  • 如果你不需要验证查询逻辑本身,可以直接调用原page实例做方法断言,不需要走关联查询。
  • 如果你需要对该id的所有Page实例都打存根,可以使用allow_any_instance_of(Page).to receive(:last_page?).and_return(last_page),注意该方法作用范围较广,尽量缩小测试上下文避免影响其他用例。
  • 如果你需要保留关联查询逻辑,可以在查询后对返回的新实例单独打存根:
    queried_page = book.pages.order("created_at DESC").first
    allow(queried_page).to receive(:last_page?).and_return(last_page)
    expect(queried_page.last_page?).to eq "Orange"
    

内容的提问来源于stack exchange,提问作者runguacrun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 17:15:08