分享不同工厂的特征

caa*_*os0 11 ruby traits factory-bot

我有许多模型可以是authorable(有一个作者字段)和/或tenancyable(有一个租户字段).所以,我写了两个问题.

问题出在测试中.我曾使用该shared_examples_for块为关注点编写测试,并将它们包含在我的模型测试中.无论如何,要做到这一点,我有几个特征和后块,例如:

after(:build) do |authorable|
  authorable.author = build(:user, tenant: authorable.tenant)
end

trait :no_author do
  after(:build) do |authorable|
    authorable.author = nil
  end
end

trait :no_tenant do
  tenant nil
end
Run Code Online (Sandbox Code Playgroud)

在所有可租赁和可授权的模型的工厂中,这段代码应该是相同的.

我没有找到任何办法做到这一点.可能吗?

fiv*_*git 14

特征可以在全球注册,因此它们可以在任何其他工厂中使用,而无需使用FactoryGirl的继承:

FactoryGirl.define do
  trait :no_author do
    after(:build) { |authorable| authorable.author = nil }
  end

  trait :no_tenant do
    tenant nil
  end

  factory :model do
    tenant  { build(:tenant) }
  end
end
Run Code Online (Sandbox Code Playgroud)

然后,您可以像这样简单地构建对象:

FactoryGirl.build(:model, :no_tenant)
FactoryGirl.build(:model, :no_author)
Run Code Online (Sandbox Code Playgroud)

after 回调也可以在全局注册,但这意味着它们会被FactoryGirl创建的任何对象触发,这可能会导致不良副作用:

FactoryGirl.define do
  after(:build) do |authorable|
    authorable.author = build(:user, tenant: authorable.tenant)
  end

  factory :model do
    tenant  { build(:tenant) }
  end

  factory :other_model
end

FactoryGirl.build(:model)       # Happiness!
FactoryGirl.build(:other_model) # undefined method `tenant'
Run Code Online (Sandbox Code Playgroud)

要避免这种情况,您可以将回调包装在特征中,就像在:no_author特征中一样,或者可以使用工厂继承:

FactoryGirl.define do
  factory :tenancyable do
    trait :no_tenant do
      tenant nil
    end

    factory :authorable do
      after(:build) do |authorable|
        authorable.author = build(:user, tenant: authorable.tenant)
      end

      trait :no_author do
        after(:build) do |authorable|
          authorable.author = nil
        end
      end
    end
  end

  factory :model, parent: :authorable, class: 'Model' do
    tenant  { build(:tenant) }
  end

  factory :other_model
end
Run Code Online (Sandbox Code Playgroud)

请注意如何在model此处明确指定工厂的类以使其工作.您现在可以构建对象:

FactoryGirl.build(:model, :no_author) # Happiness!
FactoryGirl.build(:other_model)       # More Happiness!
Run Code Online (Sandbox Code Playgroud)

使用第二种方法,特征和回调更加包含.当您拥有包含许多工厂的大型代码库时,这实际上可能会减少意外情况.