如何在RSpec中比较含字符串与Reciept模型对象的数组?
如何在RSpec中正确断言包含字符串与ActiveRecord对象的数组
你直接写eq(["IGA", #<Reciept id: 1, na...])肯定行不通,因为那个#<Reciept...>只是对象的控制台输出(inspect结果),不是实际的对象引用,而且硬编码这种字符串完全不健壮——只要对象的属性或Rails版本变一点,测试就会挂掉。下面给你几个靠谱的实现方式:
方案1:拆分断言,逐个验证元素
这种方式最清晰,能精准验证数组里的每一部分:
it "returns the expected store name and Receipt object" do result = described_class.find_store(params, user_id) # 先验证数组长度 expect(result).to have(2).items # 验证第一个元素是目标字符串 expect(result.first).to eq("IGA") # 验证第二个元素是Receipt实例,再逐个验证关键属性 receipt = result.last expect(receipt).to be_a(Receipt) expect(receipt.id).to eq(1) expect(receipt.name).to eq("IGA") expect(receipt.reciept_date).to eq(Time.parse("2006-02-18 16:25:00")) expect(receipt.user_id).to eq(user_id) end
这种方式的好处是,哪怕某个属性不匹配,RSpec会明确告诉你是哪一步出了问题,方便调试。
方案2:用预先创建的实例做对比
如果你的测试用例里已经提前创建了对应的Receipt记录(比如用工厂或者直接create),可以直接用这个实例来断言:
# 先在测试前准备好数据 let(:target_receipt) do Receipt.create!( name: "IGA", reciept_date: Time.parse("2006-02-18 16:25:00"), user_id: user_id ) end it "returns the correct store name and Receipt object" do expect(described_class.find_store(params, user_id)).to eq(["IGA", target_receipt]) end
RSpec会自动比较ActiveRecord对象的身份(如果是同一个数据库实例的话),这样你不用手动写一堆属性断言,代码更简洁。
注意事项
- 别硬编码对象的
inspect输出字符串:这种写法完全依赖控制台的格式,非常脆弱,绝对不要用。 - 检查模型名拼写:你写的
Reciept应该是Receipt吧?如果是笔误,记得修正,避免不必要的错误。 - 确保测试数据存在:不管用哪种方案,都要保证测试运行时数据库里有对应的Receipt记录,不然
find_store方法肯定找不到。
内容的提问来源于stack exchange,提问作者awsm sid
相关产品推荐
相关产品推荐

