如何禁用/存根任何Rails ActiveRecord调用进行一次测试

时间:2016-06-13 13:30:28

标签: ruby-on-rails activerecord rspec rspec-rails

假设我正在将Ruby on Rails中的特定代码片段中的功能从ActiveRecord::Base功能替换为ElasticSearch对象模型(因此在命中该对象时不会调用PostgeSQL / MySQL / SQL)用于搜索端点的/works/search

的EG序列化器

那么如何在RSpec中确保在检索数据时没有进行SQL调用(例如,如果通过ActiveRecord进行SQL调用,测试将引发异常)

1 个答案:

答案 0 :(得分:0)

勾选ActiveRecord::Base.connection应该可以解决问题。

需要注意的一件事是在完成所有准备工作(Arrange测试的一部分)之后。例如,before(:each)可以在运行测试之前清理数据库=>触发ActiveRecord.connection,您可能正在创建一些将由ElasticSearch =>索引的记录。调用ActiveRecord.connection。

这样的事情:

class WorksSearchSerializer
  attr_reader :collection

  def initialize(collection)
    @collection
  end

  def as_json
    [
      {
        id: work.id
        comment_ids: work.comments.map(&:id)
        # ... other stuff that may trigger ActiveRecord call
      }
    ]
  end
end

require 'rails_helper'

RSpec.describe WorksSearchSerializer do
  ShouldNotDoAnyDBConnection = Class.new(StandardError)

  subject { described_class.new(es_works)  }
  let!(:work) { Work.create!  } #this triggers ActiveRecord::Base.connection call
  let(:es_works) { Work.__elasticsearch__.search({query: { match_all: {} }}.to_json) }
  let(:result) { subject.as_json }

  before do
    sleep 0.2 # wait for ES reindex
  end

  it 'should not pull any relational DB records' do  
    allow(ActiveRecord::Base)
      .to receive(:connection)
      .and_raise(ShouldNotDoAnyDBConnection)

    expect(result).to be_kind_of Array

    allow(ActiveRecord::Base)
      .to receive(:connection)
      .and_call_original
  end

end