如何使用RSpec测试记忆?

时间:2013-12-18 18:10:24

标签: ruby-on-rails ruby rspec2 rspec-rails memoization

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

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

基本行为:

  1. 首次通话时会创建新记录。
  2. 随后的调用会返回相同的结果。
  3. 每次更新后重置ivar,返回后续调用中与当前环境关联的第一个(唯一)记录。
  4. 对于这种方法,我有下一个测试:

    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
    

2 个答案:

答案 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