I'm needing to stub an ActiveRecord model before it has been retrieved from the db. Here's a simplified example:
model.rb:
class Model < ActiveRecord::Base
def self.first_bar
find(id: 1).bar
end
def bar
'not the value I want'
end
end
model_spec.rb:
let(:model) { Model.create } # => <Model id:1>
before { allow(model).to receive(:bar).and_return('the value I need stubbed') }
it { expect(Model.some_value).to eq('the value I need stubbed') }
Obviously, this test fails because the object that is retrieved in Model.first_bar
is a different object than the one that was stubbed.
Caveats:
allow_any_instance_of(Model).to receive(:first_bar)
because I'm using other instances of that model elsewhere in the real test. allow(Model).to receive(:first).with(id: 1)
because for my use case, it's too brittle. Ideally, I need something like allow_any_instance_of(Model).with_attributes(id: 1)
, so any object with those particular values gets stubbed.
I can't use
allow_any_instance_of(Model).to receive(:first_bar)
because I'm using other instances of that model elsewhere in the real test.
This doesn't make sense. first_bar
is a class method, so instances would not call it. Are you familiar with the difference between class and instance methods?
I think allow(Model).to receive(:first_bar)
will give you the functionality that you are looking for.
Alternately, you could do
allow_(Model).to receive(:find).with(id:1).and_return ...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.