【问题标题】:rails/rspec: Fabricator - testing associations (ActiveModel::MissingAttributeError)rails/rspec: Fabricator - 测试关联 (ActiveModel::MissingAttributeError)
【发布时间】:2018-05-30 13:57:04
【问题描述】:

我正在为我的模型编写测试,但遇到了一个我似乎无法解决的错误。我正在使用 rspec 和 Fabricator。单独测试时一切正常,但是当我尝试测试关联时,我得到一个 ActiveModel::MissingAttributeError。

models/user.rb

class User < ApplicationRecord
  ...
  validates :email, uniqueness: true, presence: true
  belongs_to :company, required: false
end

models/company.rb

class Company < ApplicationRecord
  validates :organisation_number, uniqueness: true, presence: true
  has_many :users, dependent: :destroy
end

架构

create_table "companies", force: :cascade do |t|
  t.string "organisation_number"
  ...
end

create_table "users", id: :serial, force: :cascade do |t|
    t.string "email", default: "", null: false
    ...
    t.bigint "company_id"
    t.index ["company_id"], name: "index_users_on_company_id"
    ...
  end

fabricators/user_fabricator.rb

Fabricator :user do
  email { Faker::Internet.email }
  password '123456'
  confirmed_at Time.now
end

fabricators/company_fabricator.rb

Fabricator :company do
  organisation_number { Faker::Company.swedish_organisation_number }
end

spec/user_spec.rb(第一次测试通过,第二次失败)

describe User do
  context '#create' do
    it 'Creates a user when correct email and password provided' do
      user = Fabricate(:user)
      expect(user).to be_valid
    end
    it 'Lets assign a company to user' do
      company = Fabricate(:company)
      expect(Fabricate.build :user, company: company).to be_valid
    end
  end
end

我还尝试将公司直接添加到用户制造商,就像这样(在我看来,这就像 documentation 的正确实现):

Fabricator :user do
  email { Faker::Internet.email }
  password '123456'
  confirmed_at Time.now
  company
end

反之,将用户添加到 Company fabricator,如下所示:

Fabricator :company do
  organisation_number { Faker::Company.swedish_organisation_number }
  users(count: 3) { Fabricate(:user) }
end

但是这两种方法都给我留下了同样的错误:

User#create 让我们将公司分配给用户 失败/错误:company = Fabricate(:company)
ActiveModel::MissingAttributeError: can't write unknown attribute 'company_id'

对我做错了什么有什么建议吗?

【问题讨论】:

  • 您的用户表是否有 company_id 列,因为错误表明它没有
  • @engineersmnky 是的,确实如此。抱歉,忘记添加架构(现在更新问题)
  • 您确定您的测试数据库再次包含该列,因为错误表明company_id 不是User 的属性。确保 spec_helper 文件包含此行 ActiveRecord::Migration.maintain_test_schema! 或尝试运行 RAILS_ENV=test rake db:migrate
  • 太棒了!这做到了。如果您能多解释一下这条线的作用以及我的数据库为什么没有同步,我很乐意将其标记为已接受的答案。

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


【解决方案1】:

我会写下我自己的答案,但我不确定我是否能比RSpec 已经拥有的更好地描述它,所以这直接取自Here

Rails 4.x ActiveRecord::Migration 等待迁移检查

如果您不使用ActiveRecord,则无需担心这些 设置。

Rails 4.x 的用户现在可以利用改进的模式迁移和同步功能。在 RSpec 3 之前,用户需要在开发和测试环境中手动运行迁移。此外,行为会有所不同,具体取决于规范是通过 rake 还是通过独立的 rspec 命令运行的。

随着 Rails 4 的发布,新的 API 已经在 ActiveRecord::Migration。这使得 RSpec 可以利用这些新的 标准迁移检查,全面反映行为。

  • Rails 4.0.x

    在 Rails 完成后,将以下内容添加到 rails_helper 文件的顶部 被要求:

     ActiveRecord::Migration.check_pending!
    

    如果有任何挂起的架构更改,这将引发异常。用户仍需要手动保持开发和测试环境同步。

  • Rails 4.1+

    在此版本中,有一个令人兴奋的新功能。用户不再需要保持开发和测试环境同步。为了利用这一点,在需要 Rails 之后,将以下内容添加到 rails_helper 文件的顶部:

     ActiveRecord::Migration.maintain_test_schema!
    

    这不仅仅是在测试模式有 待迁移,Rails 将尝试加载模式。一个例外将 现在只有在架构之后有待处理的迁移时才会引发 已加载。

    使用此功能时需要注意一些注意事项:

    • 迁移仍需要手动运行;虽然现在这只需要在“开发”环境中完成

    • 如果架构尚未初始化,则会引发异常。异常将提供说明rake db:migrate 需要运行。

可以选择不检查待处理的迁移。由于这是 实际上是 Rails 的一个特性,需要作为 Rails 的一部分进行更改 配置。为此,请将以下内容添加到您的 config/environments/test.rb 文件中:

config.active_record.maintain_test_schema = false

新的 RSpec 项目无需担心这些命令,因为 rails generate rspec:install 会自动添加它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-12
    • 1970-01-01
    相关资源
    最近更新 更多