我的其中一个课程中有下一个代码:
class Settings < ActiveRecord::Base
def self.current
@settings ||= Settings.where({ environment: Rails.env }).first_or_create!
end
# Other methods
end
基本行为:
对于这种方法,我有下一个测试:
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
我对此感到不舒服,因为我实际上并没有测试memoization,所以我一直在关注this question上的方法,我尝试过类似的东西:
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
但是这个测试会返回以下错误:
NoMethodError:
undefined method `first_or_create!' for nil:NilClass
所以我的问题是,如何使用RSpec测试此方法的memoization?
更新
最后,我的方法如下:
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
答案 0 :(得分:7)
在邮件期望中添加.and_call_original
:
expect(Settings).to receive(:where).with({ environment: 'test' }).once.and_call_original
答案 1 :(得分:0)
下面的代码调用Settings.current
两次并检查它们是否彼此相等以检查该值是否已被记忆。我们还会列出我们没有测试的所有其他方法。
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