如何使用RSpec模拟数据库调用

时间:2016-07-17 16:13:37

标签: ruby-on-rails ruby rspec

我正在尝试测试JSON API端点,但我收到ActiveRecord::RecordNotFound异常,因为对user.find的调用失败。

如何模拟我的测试的活动记录调用,以便它返回一些内容并且不会抛出异常?

(我也在使用factory_girl,以防我可以使用)

def do_something
  success = false
  message = ""

  user = User.find(params[:user_id])

  if user.present?
    # ...

    if user.save!
      success = true
    end
  end

  render json: {
    "success": success,
    "message": message
  }
end

我的RSpec看起来像:

#RSpec.describe Api::UsersController, type: :controller do 

it "should return some JSON" do 
  payload = {
    user_id: "1",
    # ...
  }.to_json

  post :do_something, payload, format: :json

  expected = {
    success: false,
    message: ""
  }.to_json 

  expect(response.body).to eq(expected)
end

2 个答案:

答案 0 :(得分:1)

我认为您需要首先使用FactoryGirl创建用户,然后您可以在有效负载中传递该用户的ID,如下所示:

let(:user) { create :user } # create user by FactoryGirl

it "should return some JSON" do
  payload = {
    user_id: user.id,
    # ...
  }.to_json
  ...
end

答案 1 :(得分:0)

如果您想使用ActiveRecord模拟数据库,可以尝试这样的事情。

let(:user) { build_mock_class.new() }
before(:all) { create_table }
after(:all) { drop_table }

  def build_mock_class
    Class.new(ActiveRecord::Base) do
      self.table_name = 'mock_table'
    end
  end

  def create_table
    ActiveRecord::Base.connection.create_table :mock_table do |t|
      t.integer :user_id
      t.timestamps
    end
  end

  def drop_table
    ActiveRecord::Base.connection.drop_table :mock_table
  end

但是在继续操作之前必须建立连接,并且可以将连接适配器放在spec_helper

ActiveRecord::Base.establish_connection(
  adapter:  'sqlite3',
  database: ':memory:'
)

您可以使用您想要的任何内容更改列名称,这也将在运行规范时创建表格,并在规范传递后销毁。

注意:不要忘记在active_record或您想要使用的任何地方要求sqlite3spec_helper

希望它有所帮助。