How can I test memoization with RSpec?
memoization, rspec-rails, rspec2, ruby, ruby-on-rails
Solution
Add an `.and_call_original` to your message expectation:
expect(Settings).to receive(:where).with({ environment: 'test' }).once.and_call_original
Problem
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: - It creates a new record on first call. - It returns the same result with subsequent calls. - It resets the ivar after each update, returning the first (and unique) record associated to current environment in subsequent calls. 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 ```