Rspec 3 Rails 4 mock chained method call with parameters

I am trying to poke fun at the following line:

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

      

I tried:

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'])

      

Unfortunately, the expectation doesn't seem to match. No errors are thrown, but the methods are not mocked.

I also tried simple and dropped it working.

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

      

However, this wait is too generated and fails when it where

matches another call where

above in the code.

How can I make fun of this line?

+3


source to share


2 answers


While you can use receive_message_chain

as suggested, consider the need for complexity as an indication that your class interface can be cleaner.

The RSpec docs will say to consider any use of get_message_chain code smell.



A better approach would be to define a class method on AdminUser

named something like this publisher_emails

, which will be much easier to stub out and also improve the readability of your code.

+2


source


You can stub method calls on two-local numbers:



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

      

0


source







All Articles