【发布时间】:2020-04-22 03:59:47
【问题描述】:
早上好,
在长时间使用 Rails 之后,我正在开发一个概念验证 Rails 应用程序。我设置了 RSpec 测试,以及 FactoryBot 和 Faker 来生成测试数据。在我的应用中,我有两个模型:
class Admin::Tenant < ApplicationRecord
has_rich_text :description
has_and_belongs_to_many :users,
association_foreign_key: :admin_user_id,
foreign_key: :admin_tenant_id
has_many :tenant_groups,
inverse_of: :tenant,
dependent: :destroy,
class_name: 'Tenant::Group'
validates :name,
presence: true,
length: { maximum: 255 }
end
class Tenant::Group < ApplicationRecord
has_rich_text :description
belongs_to :tenant,
class_name: 'Admin::Tenant',
inverse_of: :tenant_groups
validates :name,
presence: true,
length: { maximum: 255 }
acts_as_tenant :tenant
end
我还定义了两个工厂:
FactoryBot.define do
factory :admin_tenant, class: 'Admin::Tenant' do
name { Faker::Lorem.sentence }
end
factory :tenant_group, class: 'Tenant::Group' do
association :tenant, factory: :admin_tenant
name { Faker::Lorem.sentence }
end
end
单独使用工厂:admin_tenant 时,它似乎工作正常,但是当我尝试生成:tenant_group(使用create(:tenant_group))时,我在rspec 中收到错误:
Failure/Error: let(:tenant_group) { create(:tenant_group) }
ActiveRecord::AssociationTypeMismatch:
Tenant(#52813860) expected, got #<Admin::Tenant id: 295, name: "Perspiciatis sit numquam fugit.", created_at: "2020-01-03 15:08:13", updated_at: "2020-01-03 15:08:13"> which is an instance of Admin::Tenant(#55283820)
似乎出于某种原因,它假设工厂的类应该是别的东西。由于我在关联中指定了class_name,我认为它会起作用(当我使用应用程序本身时它会起作用)。我看到 Spring 可能会导致问题,所以我按照 FactoryBot README 的建议并将config.before(:suite) { FactoryBot.reload } 放在我的 rails_helper.rb 文件中。
更新 1
现在发现问题在于acts_as_tenant。 RSpec 输出中的堆栈跟踪太短,无法意识到问题所在,但现在它也出现在常规使用中。
更新 2
我将继续并将其标记为已解决。正如我最初认为的那样,这似乎不是 FactoryBot 的问题,而是我对 acts_as_tenant 的理解的问题。当无法通过关联名称轻松推断类名称时,您必须指定:class_name 选项。在浏览了一些源代码之后,这一点变得清晰起来。回想起来,这似乎很明显,因为所有关联的行为方式似乎都相同......
【问题讨论】:
-
我认为这根本不是 FactoryBot 问题。 FactoryBot 实际上正在做它应该做的事情并创建一个
Admin::Tenant的实例。问题是模型中的关联本身。我没有使用 ActsAsTenant,但我的猜测是acts_as_tenant :tenant实际上定义了一个关联,该关联用不带类名选项的关联覆盖belongs_to :tenant, class_name: 'Admin::Tenant' ...。您可以致电Tenant::Group.reflect_on_association(:tenant)进行调查。 -
我认为您的代码看起来不错...有一个快速的谷歌,这些变通办法可能会有所帮助:github.com/thoughtbot/factory_bot/blob/master/…
-
尝试添加到您的 rspec 配置中:
-
RSpec.configure do |config| config.before(:suite) { FactoryBot.reload } end
标签: ruby-on-rails rspec factory-bot