簡體   English   中英

Rails - 測試夾具錯誤NoMethodError:nil的未定義方法`type':NilClass

[英]Rails - Testing fixtures error NoMethodError: undefined method `type' for nil:NilClass

我在運行使用具有模型之間關聯的夾具的測試時遇到問題。

一旦我運行rake test ,這就是我得到的錯誤:

ERROR["test_truth", SevenPortfolioTest, 0.005154775]
 test_truth#SevenPortfolioTest (0.01s)
NoMethodError:         NoMethodError: undefined method `type' for nil:NilClass


ERROR["test_should_destroy_item_video", SevenPortfolio::ItemVideosControllerTest, 0.008887804]
 test_should_destroy_item_video#SevenPortfolio::ItemVideosControllerTest (0.01s)
NoMethodError:         NoMethodError: undefined method `type' for nil:NilClass


ERROR["test_should_get_index", SevenPortfolio::ItemVideosControllerTest, 0.011364416]
 test_should_get_index#SevenPortfolio::ItemVideosControllerTest (0.01s)
NoMethodError:         NoMethodError: undefined method `type' for nil:NilClass


ERROR["test_should_create_item_video", SevenPortfolio::ItemVideosControllerTest, 0.014584266]
 test_should_create_item_video#SevenPortfolio::ItemVideosControllerTest (0.01s)
NoMethodError:         NoMethodError: undefined method `type' for nil:NilClass


ERROR["test_should_get_new", SevenPortfolio::ItemVideosControllerTest, 0.017282812]
 test_should_get_new#SevenPortfolio::ItemVideosControllerTest (0.02s)
NoMethodError:         NoMethodError: undefined method `type' for nil:NilClass


ERROR["test_should_update_item_video", SevenPortfolio::ItemVideosControllerTest, 0.019729858]
 test_should_update_item_video#SevenPortfolio::ItemVideosControllerTest (0.02s)
NoMethodError:         NoMethodError: undefined method `type' for nil:NilClass


ERROR["test_should_get_edit", SevenPortfolio::ItemVideosControllerTest, 0.022365633]
 test_should_get_edit#SevenPortfolio::ItemVideosControllerTest (0.02s)
NoMethodError:         NoMethodError: undefined method `type' for nil:NilClass


ERROR["test_should_destroy_item", SevenPortfolio::ItemsControllerTest, 0.025860205]
 test_should_destroy_item#SevenPortfolio::ItemsControllerTest (0.03s)
NoMethodError:         NoMethodError: undefined method `type' for nil:NilClass


ERROR["test_should_get_edit", SevenPortfolio::ItemsControllerTest, 0.030867796]
 test_should_get_edit#SevenPortfolio::ItemsControllerTest (0.03s)
NoMethodError:         NoMethodError: undefined method `type' for nil:NilClass


ERROR["test_should_show_item", SevenPortfolio::ItemsControllerTest, 0.036687105]
 test_should_show_item#SevenPortfolio::ItemsControllerTest (0.04s)
NoMethodError:         NoMethodError: undefined method `type' for nil:NilClass


ERROR["test_should_update_item", SevenPortfolio::ItemsControllerTest, 0.040130774]
 test_should_update_item#SevenPortfolio::ItemsControllerTest (0.04s)
NoMethodError:         NoMethodError: undefined method `type' for nil:NilClass


ERROR["test_should_create_item_with_video", SevenPortfolio::ItemsControllerTest, 0.042776553]
 test_should_create_item_with_video#SevenPortfolio::ItemsControllerTest (0.04s)
NoMethodError:         NoMethodError: undefined method `type' for nil:NilClass


ERROR["test_should_get_index", SevenPortfolio::ItemsControllerTest, 0.045301694]
 test_should_get_index#SevenPortfolio::ItemsControllerTest (0.05s)
NoMethodError:         NoMethodError: undefined method `type' for nil:NilClass


ERROR["test_should_get_new", SevenPortfolio::ItemsControllerTest, 0.048094189]
 test_should_get_new#SevenPortfolio::ItemsControllerTest (0.05s)
NoMethodError:         NoMethodError: undefined method `type' for nil:NilClass


ERROR["test_should_create_item_with_gallery", SevenPortfolio::ItemsControllerTest, 0.051019403]
 test_should_create_item_with_gallery#SevenPortfolio::ItemsControllerTest (0.05s)
NoMethodError:         NoMethodError: undefined method `type' for nil:NilClass

我正在測試一個rails引擎。 這是我的裝置:

# test/fixtures/seven_portfolio/items.yml
item_one:
  description: item one description
  finished_at: <%= 7.days.ago %>
  is_featured: true
  item_type: 0

item_two:
  description: item two description
  finished_at: <%= 6.days.ago %>
  is_featured: false
  item_type: 1


# test/fixtures/seven_gallery/galleries.yml
gallery_one:
  title: seven_gallery_gallery_one_title
  item: item_one

# test/fixtures/seven_gallery/photos.yml
photo_one:
  caption: photo_one_caption
  gallery: gallery_one

# test/fixtures/seven_portfolio/item_videos.yml
one:
  item: item_one

例如,當我刪除item: item_one和類似的關聯item: item_one 測試效果很好。

- 編輯

這是回溯

Command failed with status (1): [ruby -I"lib:lib:test"  "/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/rake_test_loader.rb" "test/**/*_test.rb" ]

/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/testtask.rb:108:in `block (3 levels) in define'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/file_utils.rb:57:in `call'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/file_utils.rb:57:in `sh'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/file_utils_ext.rb:37:in `sh'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/file_utils.rb:96:in `ruby'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/file_utils_ext.rb:37:in `ruby'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/testtask.rb:104:in `block (2 levels) in define'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/file_utils_ext.rb:58:in `verbose'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/testtask.rb:100:in `block in define'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/task.rb:240:in `call'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/task.rb:240:in `block in execute'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/task.rb:235:in `each'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/task.rb:235:in `execute'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/task.rb:179:in `block in invoke_with_call_chain'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/monitor.rb:211:in `mon_synchronize'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/task.rb:172:in `invoke_with_call_chain'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/task.rb:165:in `invoke'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/application.rb:150:in `invoke_task'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/application.rb:106:in `block (2 levels) in top_level'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/application.rb:106:in `each'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/application.rb:106:in `block in top_level'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/application.rb:115:in `run_with_threads'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/application.rb:100:in `top_level'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/application.rb:78:in `block in run'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/application.rb:176:in `standard_exception_handling'
/home/rafael/.rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/application.rb:75:in `run'
/home/rafael/.rbenv/versions/2.2.0/bin/rake:33:in `<main>'

編輯

這是Item類:

module SevenPortfolio
  class Item < ActiveRecord::Base
    has_one :item_video, class_name:'SevenPortfolio::ItemVideo', foreign_key: "seven_portfolio_item_id"
    has_one :item_gallery, class_name: 'SevenGallery::Gallery', foreign_key: "seven_portfolio_item_id"
    accepts_nested_attributes_for :item_video, :item_gallery

    before_save :process_type

    def process_type
      self.build_item_video if self.item_type == 0
      self.build_item_gallery if self.item_type == 1
    end

    def type_content
      self.item_gallery if self.item_type == 0
      self.item_video if self.item_type == 1
    end
  end
end

Gallery類:

class SevenGallery::Gallery < ActiveRecord::Base
  include SevenGallery::Concerns::Gallery
  belongs_to :item, :class_name => 'SevenPortfolio::Item'
end

編輯這是schema.rb文件:

ActiveRecord::Schema.define(version: 20150414145951) do

  create_table "seven_gallery_galleries", force: :cascade do |t|
    t.string   "title",                   limit: 255
    t.datetime "created_at",                          null: false
    t.datetime "updated_at",                          null: false
    t.integer  "seven_portfolio_item_id", limit: 4
  end

  add_index "seven_gallery_galleries", ["seven_portfolio_item_id"], name: "index_seven_gallery_galleries_on_seven_portfolio_item_id", using: :btree

  create_table "seven_gallery_photos", force: :cascade do |t|
    t.string   "caption",                  limit: 255
    t.string   "image",                    limit: 255
    t.integer  "seven_gallery_gallery_id", limit: 4
    t.datetime "created_at",                                             null: false
    t.datetime "updated_at",                                             null: false
    t.boolean  "is_new",                   limit: 1,     default: true
    t.boolean  "is_featured",              limit: 1,     default: false
    t.text     "description",              limit: 65535
    t.string   "alt",                      limit: 255
    t.integer  "position",                 limit: 4,     default: 0
  end

  add_index "seven_gallery_photos", ["seven_gallery_gallery_id"], name: "index_seven_gallery_photos_on_seven_gallery_gallery_id", using: :btree

  create_table "seven_portfolio_item_videos", force: :cascade do |t|
    t.string   "url",                     limit: 255
    t.text     "description",             limit: 65535
    t.string   "title",                   limit: 255
    t.integer  "seven_portfolio_item_id", limit: 4
    t.datetime "created_at",                            null: false
    t.datetime "updated_at",                            null: false
  end

  add_index "seven_portfolio_item_videos", ["seven_portfolio_item_id"], name: "index_seven_portfolio_item_videos_on_seven_portfolio_item_id", using: :btree

  create_table "seven_portfolio_items", force: :cascade do |t|
    t.datetime "created_at",                                null: false
    t.datetime "updated_at",                                null: false
    t.text     "description", limit: 65535
    t.date     "finished_at"
    t.boolean  "is_featured", limit: 1,     default: false
    t.integer  "item_type",   limit: 4,     default: 0
  end

  add_foreign_key "seven_gallery_galleries", "seven_portfolio_items", on_delete: :cascade
  add_foreign_key "seven_gallery_photos", "seven_gallery_galleries", on_delete: :cascade
  add_foreign_key "seven_portfolio_item_videos", "seven_portfolio_items", on_delete: :cascade
end

在我的開發環境中遷移和回滾幾次后,我遇到了同樣的錯誤。 這與“_type”列有關。

為我修復它的唯一方法是刪除/創建測試數據庫:

bundle exec rake db:reset RAILS_ENV=test

在執行此操作之前,請確保您的schema.rb處於良好狀態。

在模型中創建一個在db中沒有字段的關系時會發生此錯誤。 例:

class Contact < ActiveRecord::Base
 belongs_to account
end

但在你的表聯系人:

create_table "contacts", force: :cascade do |t|
    t.string   "fname"
    t.string   "lname"
    t.string   "title"
    t.string   "description"
    t.datetime "created_at",                 null: false
    t.datetime "updated_at",                 null: false
    t.boolean  "primary"
    t.integer  "contactable_id"
    t.integer  "contactable_type"
  end

看到沒有account_id字段。

在我的情況下,我忘了更新模型的belongs_to是多態的:

class Contact < ActiveRecord::Base
  belongs_to :contactable, polymorphic: true
end

class Account < ActiveRecord::Base
  has_many :contacts, as: :contactable
end

這不是這個問題的重復/類似問題嗎?

測試時按特定順序裝載導軌夾具

可能發生的事情是你的燈具沒有以正確的順序加載,因此當引用項目時它會出現為零。

從其他答案的回答你可以嘗試

以下是解決問題的方法:

  1. 使用默認超級用戶登錄Postgresql(我的是“postgres”)執行以下命令:

  2. ALTER ROLE yourtestdbuser with SUPERUSER;

  3. 享受你正常工作的燈具。

如果您使用的是mysql,那可能是類似的問題。

TL; DR:人們出於不同的原因登陸這個問題。 我的問題/解決方案在“修復錯誤”中描述。 我希望這個擴展的解釋將幫助您了解為什么您遇到這個神秘的錯誤,並節省您一些時間調試它。

如何診斷這個問題

我在運行測試時遇到了幾乎相同的錯誤: NoMethodError: undefined method 'id' for nil:NilClass ,或NoMethodError: undefined method 'each' for nil:NilClass 沒有行號可供參考, 盧卡斯的重建答案 有時會起作用,然后就會停止工作; 我后來才知道這是因為夾具文件的緩存和加載順序。

查找拋出錯誤的位置

我的錯誤在於如何設置我的燈具。 我通過在StackOverflow回答中描述的完整回溯運行我的測試找到了這個:

BACKTRACE=YES rake test test/controllers/document_submissions_controller_test.rb

這指向ActiveSupport中拋出錯誤的gem文件。 這是我單個測試的完整日志:

在此輸入圖像描述

所以似乎錯誤在於加載我的燈具,因為錯誤源自active_record/fixtures.rb:758 (見上面突出顯示的行)。 但是,我的應用程序中有大量的燈具,我需要縮小范圍,特別是導致問題。

設置一個斷點

我使用以下命令在代碼編輯器中打開了active_record/fixtures.rb:758文件:

code /Users/mattmcinnis/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.0/lib/active_record/fixtures.rb

注意:我正在使用VSCode和code命令,但任何代碼編輯器都可以。

在發生錯誤的第758行,我看到了這段代碼:

FixtureSet::File.open(file) do |fh|
  fh.each do |fixture_name, row|  # line 758
    fixtures[fixture_name] = ActiveRecord::Fixture.new(row, model_class)
  end 
end

..我在救援區包裹,並修改為:

FixtureSet::File.open(file) do |fh|
  begin
    fh.each do |fixture_name, row|
      fixtures[fixture_name] = ActiveRecord::Fixture.new(row, model_class)
    end
  rescue
    debugger
  end
end

注意:完成后,請務必還原對此文件的任何更改!

查找問題文件

我感興趣的是在變量fh上面循環中捕獲的文件導致了錯誤。 再次運行我的測試套件我點擊我的斷點並找到導致問題的文件名:

> (byebug) fh
  => ... @file="permissions.yml"

修復錯誤

在我的permissions.yml文件中,我的fixture通過硬編碼'id'來引用相關模型,而不是通過名稱引用:

防爆。 permissions.yml

permission1:
  ...
  user_id: <%= User.first.id %>  # Bad!

修復最后一行,例如user: user1引用users.ymluser1 fixture解決了這個問題。

希望這有助於某人。 我在這一天失去了半天,發現診斷起來非常困難。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM