Add an .and_call_original
to your message expectation:
expect(Settings).to receive(:where).with({ environment: 'test' }).once.and_call_original
Pregunta
I have the next code in one of my classes:
class Settings < ActiveRecord::Base
def self.current
@settings ||= Settings.where({ environment: Rails.env }).first_or_create!
end
# Other methods
end
Basic behaviour:
For this method I have the next test:
describe Settings do
describe ".current" do
it "gets all settings for current environment" do
expect(Settings.current).to eq(Settings.where({ environment: 'test' }).first)
end
end
end
I don't feel comfortable with that because I'm actually not testing memoization, so I have been following the approach on this question, and I have tried something like that:
describe ".current" do
it "gets all settings for current environment" do
expect(Settings).to receive(:where).with({ environment: 'test' }).once
2.times { Settings.current }
end
end
But this test returns the following error:
NoMethodError:
undefined method `first_or_create!' for nil:NilClass
So my question is, how can I test memoization on this method with RSpec?
UPDATE:
Finally, my approach is as follows:
describe Settings do
describe ".current" do
it "gets all settings for current environment" do
expect(described_class.current).to eq(described_class.where(environment: 'test').first)
end
it "memoizes the settings for current environment in subsequent calls" do
expect(described_class).to receive(:where).once.with(environment: 'test').and_call_original
2.times { described_class.current }
end
end
end
Solución
Add an .and_call_original
to your message expectation:
expect(Settings).to receive(:where).with({ environment: 'test' }).once.and_call_original
Otros consejos
The code below calls Settings.current
twice and checks if they are both equal to each other to check if the value has been memoized. We also stub out all other methods that we aren't testing.
describe ".current" do
it "gets all settings for current environment" do
relation = double("relation")
expect(relation).to receive(:first_or_create!).once
expect(Settings).to receive(:where).with({ environment: 'test' }).once.and_return(relation)
settings = Settings.current
expect(Settings.current).to eq settings
end
end