【问题标题】:RSpec - Undefined method `key?'RSpec - 未定义的方法“键?”
【发布时间】:2015-08-01 19:55:34
【问题描述】:

我正在尝试为渲染模板运行测试并遇到错误:

undefined method `key?' for 1014:Fixnum

我的模型实例的存根在我的路由测试中可以正常工作,但在这里没有那么多。我做错了什么?

describe RestaurantsController do
  let(:restaurant) { FactoryGirl.build_stubbed(:restaurant) }

  describe 'GET #show' do
    before { get :show, restaurant.id }

    it { should render_template('show') }
  end
end

完全错误

 1) RestaurantsController GET #show 
     Failure/Error: before { get :show, restaurant.id }
     NoMethodError:
       undefined method `key?' for 1014:Fixnum
     # /Library/Ruby/Gems/2.0.0/gems/actionpack-4.2.0/lib/action_controller/test_case.rb:744:in `html_format?'
     # /Library/Ruby/Gems/2.0.0/gems/actionpack-4.2.0/lib/action_controller/test_case.rb:598:in `process'
     # /Library/Ruby/Gems/2.0.0/gems/actionpack-4.2.0/lib/action_controller/test_case.rb:65:in `process'
     # /Library/Ruby/Gems/2.0.0/gems/devise-3.5.1/lib/devise/test_helpers.rb:19:in `block in process'
     # /Library/Ruby/Gems/2.0.0/gems/devise-3.5.1/lib/devise/test_helpers.rb:72:in `catch'
     # /Library/Ruby/Gems/2.0.0/gems/devise-3.5.1/lib/devise/test_helpers.rb:72:in `_catch_warden'
     # /Library/Ruby/Gems/2.0.0/gems/devise-3.5.1/lib/devise/test_helpers.rb:19:in `process'
     # /Library/Ruby/Gems/2.0.0/gems/actionpack-4.2.0/lib/action_controller/test_case.rb:505:in `get'
     # ./spec/controllers/restaurants_controller_spec.rb:15:in `block (3 levels) in <top (required)>'

【问题讨论】:

  • get :show, id: restaurant
  • 这样我得到:Failure/Error: before { get :show, id: restaurant } ActiveRecord::RecordNotFound: Couldn't find Restaurant
  • Couldn't find Restaurantraise 因为你build_*,餐厅而不是create_*
  • @Зелёный 如果我要验证我的 Restaurant 模型的唯一性,我不会遇到重复错误吗?
  • 如果您不将记录保存到数据库,则无法通过 show 操作获取它。为避免唯一性错误,请使用 database-cleaner

标签: ruby-on-rails testing rspec tdd shoulda


【解决方案1】:

get 采取行动和参数散列(除其他外)。它不会隐式地取一个模型并将其转换为{ id: model.to_param }

相反,您需要明确指定参数。

describe RestaurantsController do
  let(:restaurant) { create(:restaurant) }

  subject { response }

  describe 'GET #show' do
    before { get :show, id: restaurant }
    it { should render_template('show') }
  end
end

正如@Зелёный 已经提到的,您需要将记录实际保存到数据库中,以便能够在控制器规范中使用它。

为避免重复问题和测试排序问题,您应该在每个示例之间清空数据库。 database_cleaner gem 对于这项任务非常宝贵。

此外,如果您需要在同一规范中创建多个记录,您可以在 factory girl 中使用序列:

FactoryGirl.define do
  factory :user do
    email { |n| "test-#{n}@example.com" }
  end
end

gem ffaker 非常适合生成电子邮件、用户名等。

补充:

您可以通过在 rails_helper 中包含 FactoryGirl 的方法来为 FactoryGirl 设置快捷方式:

RSpec.configure do |config|
  # ...
  config.include FactoryGirl::Syntax::Methods
end

这让您可以使用 FactoryGirl 方法,而无需像这样输入模块名称:

let(:restaurant) { create(:restaurant) }

【讨论】:

  • subject { response } 到底是做什么的?
  • 另外,对于您答案的第二行,它必须是 let(:restaurant) { FactoryGirl.create(:restaurant) } 才能使测试正常工作。一旦解决了这个问题,我将非常乐意将此答案标记为正确。
  • 只需将 FactoryGirl 语法包含在您的 rails 助手中即可。 subject { response } 将主题设置为响应对象而不是控制器。如果你想写像it { should have_http_status :success }这样的单行代码,它是必需的
  • 非常感谢您的帮助。
  • 你不应该需要subject { response } -- render_template 应该在控制器实例上工作(这是控制器测试中的默认主题)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多