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?
source to share
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.
source to share
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
source to share