Rspec 3 Rails 4带参数的模拟链式方法调用

时间:2015-05-13 13:22:33

标签: ruby-on-rails rspec mocking

我正在尝试模拟以下一行:

publishers = AdminUser.where(can_publish: true).pluck(:email)

我试过了:

relation = instance_double('AdminUser::ActiveRecord_Relation')
allow(AdminUser).to receive(:where).with(can_publish: true).and_return(relation)
allow(relation).to receive(:pluck).with(:email).and_return(['email', 'email2'])

不幸的是,期望似乎并不匹配。不会抛出任何错误,但这些方法并非模拟

我也尝试过,让我们采取行动。

  allow(AdminUser).to receive(:where).with(can_publish: true).and_return([object, object2])

但是,当where匹配代码中较高的另一个where调用时,此期望过于生成并失败。

我该如何模仿这条线?

2 个答案:

答案 0 :(得分:2)

尽管您可以按照建议使用receive_message_chain,但请将此类复杂性视为表明您的班级界面更清晰。

RSpec docs say考虑使用receive_message_chain代码嗅觉

更好的方法是在AdminUser上定义一个名为publisher_emails的类方法,它可以更简单地存根,并且还提高了代码的可读性。

答案 1 :(得分:1)

你可以对双打进行存根方法调用:

require 'rails_helper'

RSpec.describe AdminUser, type: :model do
  let(:expected) { ["a@example.com"] }
  let(:relation) { double(pluck: expected) }

  it "returns the expected value" do
    allow(AdminUser).to receive(:where).with(can_publish: true).and_return(relation)
    publishers = AdminUser.where(can_publish: true).pluck(:email)
    expect(publishers).to eq expected
  end
end