简体   繁体   中英

RSpec stub object that doesn't exist yet

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:

  • 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.
  • I can't use 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM