2

I have a statement like Model.some_scope.pluck(:a_field) in a method I'd like to test.

What's the recommended way for me to stub the return value of this chained method call statement with rspec-mocks 3.4.0? I saw that stub_chain and receive_message_chain are both listed as old syntax on the RSpec website.

Best Regards.

1 Answer 1

3

The cleanest way to test that code is to extract a method, e.g.

class Model < ActiveRecord::Base
  def self.some_scope_fields
    some_scope.pluck(:a_field)
  end
end

That method can be stubbed without a chain.

However, there are times when it's neither convenient nor idiomatic to do that. For example, it's idiomatic, and not a Law of Demeter violation, to call create on an ActiveRecord model's association methods. In those cases,

  • if you don't care about method arguments, use receive_message_chain. stub_chain is deprecated; receive_message_chain is not. What the receive_message_chain documentation says is that "support for stub_chain parity may be removed in future versions". The issue linked to from that documentation makes it clear that "stub chain parity" means the use of with with receive_message_chain. So do use receive_message_chain; just don't use with with it.

  • if you do care about method arguments, use doubles. For example, for the code you gave,

    scope = double
    allow(scope).to receive(:pluck).with(:a_field) { # return whatever }
    allow(Model).to receive(:some_scope).with(no_args) { scope }
    
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.