ruby-on-rails – 如何使用RSpec测试memoization?

我的其中一个课程中有下一个代码

class Settings < ActiveRecord::Base
  def self.current
    @settings ||= Settings.where({ environment: Rails.env }).first_or_create!
  end
  # Other methods
end

基本行为:

>它在第一次通话时创建新记录.
>它随后的调用返回相同的结果.
>它在每次更新后重置ivar,返回与后续调用中当前环境关联的第一个(也是唯一的)记录.

对于这种方法,我有一个测试:

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

解决方法

在您的邮件期望中添加.and_call_original:

expect(Settings).to receive(:where).with({ environment: 'test' }).once.and_call_original

相关文章

validates:conclusion,:presence=>true,:inclusion=>{...
一、redis集群搭建redis3.0以前,提供了Sentinel工具来监控各...
分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣...
上一篇博文 ruby传参之引用类型 里边定义了一个方法名 mo...
一编程与编程语言 什么是编程语言? 能够被计算机所识别的表...
Ruby类和对象Ruby是一种完美的面向对象编程语言。面向对象编...