我是FactoryGirl的新手,我正在尝试以下简单方案?
factory :female, :class => Gender do
code 'Female'
end
factory :male, :class => Gender do
code 'Male'
end
factory :papas, :class => Customer do
first_name 'Jim'
last_name 'Papas'
association :gender, :factory => :male, :strategy => :build
end
factory :dumas, :class => Customer do
first_name 'Mary'
last_name 'Dumas'
association :gender, :factory => :female, :strategy => :build
end
然后在我的测试中:
create(:male)
create(:female)
create(:papas)
create(:dumas)
请注意,Customer类具有关联belongs_to
Gender
类和验证规则,该规则指出应存在gender_id
。我还在Gender
类上验证了代码的唯一性。
在上面的create(:papas)
语句中,在我的测试中,我收到了将要创建的Customer
无效的错误,因为gender_id
是nil
。
如果我删除:strategy => :build
Customer
工厂关联中的:papas
性别问题,那么我会收到错误,在尝试创建:papas
时,代码为性别已经存在。
我需要做什么才能让我的测试按照上面的要求创建数据?
请注意,在其他测试中,我希望在没有客户的情况下创建性别。不要告诉我使用工厂创建命令创建客户,让客户同时创建性别。如果我尝试创建两个性别相同的客户,这将无效。
此外,必须有一个比一个更好的答案:
@male = create(:male)
@female = create(:female)
create(:papas, :gender => @male)
create(:dumas, :gender => @female)
(当使用固定装置时,这些东西已经开箱即用了。我会回到固定装置吗?)
答案 0 :(得分:14)
您可以通过不使用性别实例的工厂和在客户工厂中使用回调来实现您的目标。
你现在没有从性别工厂中获得很多收益(尽管我很欣赏它可能会被简化以便提出这个问题)。您可以轻松地做到这一点来获得性别:
Gender.find_or_create_by_code!('Male')
然后在您的客户工厂中,您可以使用之前的回调来设置性别:
factory :dumas, :class => Customer do
first_name 'Mary'
last_name 'Dumas'
before_create do |customer|
customer.gender = Gender.find_or_create_by_code!('Female')
end
end
在factory_girl中使用回调的格式最近已经改变,所以如果你使用3.3或更高版本,你需要这样做:
before(:create) do |customer|
而不是before_create
。
如果创建性别比您的示例更复杂,您仍然可以使用工厂创建性别,但使用find_by_code!
find_or_create_by_code!
的{{1}}内容使用回调将其与客户联系起来。
答案 1 :(得分:6)
ignore
已被弃用,将在Factory Girl的第5版中删除。
相反,您可以使用transient attributes:
factory :dumas, :class => Customer do
transient do
female { Gender.find_by_code('Female') || create(:female) }
end
first_name 'Mary'
last_name 'Dumas'
gender { female }
end
答案 2 :(得分:5)
ignore
块也可以用来包装它:
factory :dumas, :class => Customer do
ignore do
female { Gender.find_by_code('Female') || create(:female) }
end
first_name 'Mary'
last_name 'Dumas'
gender { female }
end