Just wondering if/how arguments can be passed in rspec stub chains. To give an example, suppose I have the following action:
def index
@payments = Payment.order(:updated_at).where(:paid => true)
@bad_payments = Payment.order(:some_other_field).where(:paid => false)
end
In my controller spec, I'd like to be able to stub out both methods and return different results. If only the @payments
field were in the action I'd use something like
Payment.stub_chain(:order, :where) { return_this }
But of course, that will return the same value for @bad_payments
.
So - in short, how do I include the :updated_at
and :paid => true
as stub conditions?
You can use this:
Payment.stub_chain(:order, :where).with(:updated_at).with(:paid => true) { return_this }
With rspec > 3
use this syntax:
expect(Converter).to receive_message_chain("new.update_value").with('test').with(no_args)
instead of stub_chain
.
Read more about message chains in the documenation. And here is the argument matchers documentation.
You can use nested stub block. The block can accept arguments, and the return value is used as function return value.
I use tap
because stub
does not returns the callee. The mock created by double
is returned as the result of method order
, which where
method is stub again.
Payment.stub(:order) { |order|
double('ordered_payments').tap { |proxy|
proxy.stub(:where) { |where|
[order, where]
}
}
}
Payment.order(:updated_at).where(:paid => true)
# => returns [:updated_at, {:paid => true}]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With