FactoryGirl - 基于其他对象的默认值属性

时间:2014-03-07 21:40:32

标签: factory-bot

我有以下工厂:

FactoryGirl.define do
  skip_create

  sequence :group_name do |n|
    "Group #{n}"
  end

  factory :group do
    name { generate(:group_name) }
  end

  factory :user do
    first_name "John"
    group
  end
end

但是有些情况下我想要为用户组设置默认值(而不是为每个用户创建新组)。所以我尝试这样的事情:

describe User do
  let(:our_group) { build(:group) }
  let(:other_group) { build(:group) }

  before do
    FactoryGirl.modify do
      factory :user do
        group { our_group }
      end
    end
  end

  it "users are created in same group by default" do
    user1 = build(:user)
    user2 = build(:user)
    user3 = build(:user, :group => other_group)

    expect(user1.group).to eq user2.group
    expect(user3.group).not_to eq group
  end

  it "user can attend event if #of users in same group is large enough" do
    user1 = build(:user)
    user2 = build(:user)
    user3 = build(:user)

    expect(user1.can_attend_event?).to be_true
  end
end

然而这失败了,如:

 Failure/Error: group { our_group }
 NoMethodError:
   undefined method `our_group' for #<FactoryGirl::SyntaxRunner:0x000000042c0110>

重要的是,我不想将build(:user)的许多现有语句修改为build(:user, :group => our_group)。我希望有一个地方可以设置此默认值(对于整个规范或可能更多)。

有没有办法实现我正在寻找的东西?

1 个答案:

答案 0 :(得分:1)

你可以这样做:

  sequence :group_name do |n|
    "Group #{n}"
  end

  factory :group do
    name { generate(:group_name) }

    factory :default_group do
      name "default group"
    end
  end

  factory :user do
    first_name "John"
    association :group, factory: :default_group
  end

然后在你的测试中:

describe User do
  let(:other_group) { build(:group) }

  it "users are created in same group by default" do
    user1 = build(:user)
    user2 = build(:user)
    user3 = build(:user, group: other_group)

    expect(user1.group.name).to eq user2.group.name
    expect(user3.group.name).not_to eq group.name
  end
end

如果您确实希望实例在默认情况下匹配(而不仅仅是名称),则必须构建默认组对象并在每次构建用户时分配它; FactoryGirl在隐式构建关联时不会重用同一个实例。