factory_girl中的预定义列表

时间:2014-05-13 00:21:34

标签: ruby-on-rails factory-bot

我有一个Member模型,其中包含两个状态机stateaccount。我想使用factory_girl在我的测试中创建所有可能的州和帐户组合的预定义列表。

例如,使用以下组合:

combinations = [
  [:state_a, :account_a], [:state_a, :account_b], [:state_a, :account_c],
  [:state_b, :account_a], [:state_b, :account_b], [:state_b, :account_c],
  [:state_c, :account_a], [:state_c, :account_b], [:state_c, :account_c]
]

我喜欢某种助手,例如create_list_for_all_states_and_accounts会创建:

[
  Member(state: 'a', account: 'a'),
  Member(state: 'a', account: 'b'),
  Member(state: 'a', account: 'c'),
  Member(state: 'b', account: 'a'),
  # ...
]

这可能在factory_girl吗?

2 个答案:

答案 0 :(得分:0)

评论中建议的最简单的解决方案是使用您的帮助方法在spec/support中的文件中定义辅助方法,然后在您需要的任何地方的规范中使用它:

def create_list_for_all_states_and_accounts(states = %w[ a b c ], accounts = %w[ a b c ])
  states.product(accounts).map do |state, account|
    Member.create(state: state, account: account)
  end
end

或者,如果您始终拥有相同的州和帐户名称,则可以执行此操作:

def create_list_for_all_states_and_accounts(names = %w[ a b c ])
  names.repeated_permutation(2).map do |state, account|
    Member.create(state: state, account: account)
  end
end

如果你真的想使用FactoryGirl来创建使用traits的实例,你可以像这样定义一个工厂:

factory :member do
  %w[ a b c ].product(%w[ a b c ]).each do |state, account|
    trait :"state_#{state}_account_#{account}" do
      state     state
      account   account
    end
  end
end

这将使您能够创建这样的实例:

FactoryGirl.create(:member, :state_a_account_b)

答案 1 :(得分:0)

我发现了一些有点hacky的东西,但是做到这一点非常强大和有效。我想使用factory_girl创建一组bundle,它们基本上都是种子数据(但是因为我在测试中使用了database_cleaner,所以我不能只使用seed.rb)。我是这样做的:

FactoryGirl.define do
  factory :bundle do
    factory :all_bundles do
      price  1
      name   "bronze"

      after :create do
        FactoryGirl.create :silver_bundle
        FactoryGirl.create :gold_bundle
        FactoryGirl.create :platinum_bundle
      end
    end

    factory :silver_bundle do
      price  2
      name   "silver"
    end

    factory :gold_bundle do
      price  3
      name   "gold"
    end

    factory :platinum_bundle do
      price  4
      name   "platinum"
    end
  end
end

之后,我致电create :all_bundles,我已经完成了。

所以这里的想法是:

  1. 定义所有工厂
  2. 在第一个中,添加after :create块(和/或after :stub块,如果需要的话)调用其他工厂
  3. 请注意,after :create块应该在subfactory(all_bundles这里)而不是在父工厂(bundle)中,或者每个subfactory都会执行它:)