测试方法是否命中数据库

时间:2015-08-07 14:50:01

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

我有以下方法,我想确保它不会命中数据库,除非子域发生更改。

class ApplicationController < ActionController::API
  def current_account
    unless @current_account && @current_account.subdomain == request.subdomain
      @current_account = Account.find_by subdomain: request.subdomain
    end
    @current_account
  end
end

我怎样才能测试那个?

require 'rails_helper'
RSpec.describe ApplicationController, type: :controller do
  controller do
    def index
    end
  end

  describe 'current_account' do
    before(:each) do
      FactoryGirl.create(:account, subdomain: 'subdomain1')
      FactoryGirl.create(:account, subdomain: 'subdomain2')
      request.host = 'subdomain1.example.com'
    end

    it 'sets the current_account based on the subdomain' do
      get :index
      expect(subject.send(:current_account).subdomain).to eq('subdomain1')
    end

    it 'changes the current_account when subdomain changes' do
      get :index
      request.host = 'subdomain2.example.com'
      get :index
      expect(subject.send(:current_account).subdomain).to eq('subdomain2')
    end

    xit 'does not hit the database if subdomain does not change' do
      get :index
      # expect to hit the db
      get :index
      # expect to not hit the db
    end
  end
end

我尝试expect(Account).to receive(:find)但没有成功。

2 个答案:

答案 0 :(得分:0)

我通常会为此目的安装此gem:

https://github.com/brigade/db-query-matchers - RSpec匹配数据库查询

使用示例:

it 'does not make database queries' do
  expect { subject.make_no_queries }.to_not make_database_queries
end

答案 1 :(得分:0)

我知道这很老了,但是我只是在寻找答案,所以也许其他人会受益,因为我不需要宝石来满足我的需求。

答案的要点是:如果您不需要计算实际的数据库查询或命中数(我没有,或者看起来好像OP也没有),则可以只需使用spies on a partial double来检查是否正在调用运行数据库查询的方法。但是,在运行所监视的方法之前,您始终必须做间谍。语法为allow(foo).to receive(:bar)expect(foo).to have_received(:bar)

所以OP的expect(Account).to receive(:find)不起作用的原因是,它应该是:

it 'does not hit the database if subdomain does not change' do
  # SET THE SPY
  allow(Account).to receive(:find)

  get :index
  # expect to hit the db
  expect(Account).to have_received(:find)

  get :index
  # expect to not hit the db
  expect(Account).to_not have_received(:find)
end

可以变得更加复杂,可以监视特定的查询,并且可以根据需要进行查询,因为可以expect(foo).to have_received(:bar).with(*args).twice等,但是如果您使用的是ActiveRecord而且您的方法可以进行各种查询,我想是,使用gem来计数数据库命中次数要比自己进入源代码来找出要监视的内容要容易得多。