fea*_*ool 16 ruby-on-rails-3 factory-bot
我想在控制器测试中使用FactoryGirl.attributes_for,如:
it "raise error creating a new PremiseGroup for this user" do
expect {
post :create, {:premise_group => FactoryGirl.attributes_for(:premise_group)}
}.to raise_error(CanCan::AccessDenied)
end
Run Code Online (Sandbox Code Playgroud)
...但这不起作用,因为#attributes_for省略了:user_id属性.这里的区别#create和#attributes_for:
>> FactoryGirl.create(:premise_group)
=> #<PremiseGroup id: 3, name: "PremiseGroup_4", user_id: 6, is_visible: false, is_open: false)
>> FactoryGirl.attributes_for(:premise_group)
=> {:name=>"PremiseGroup_5", :is_visible=>false, :is_open=>false}
Run Code Online (Sandbox Code Playgroud)
请注意:不存在:user_id #attributes_for.这是预期的行为吗?
FWIW,我的工厂文件包含的定义:premise_group和:user:
FactoryGirl.define do
...
factory :premise_group do
sequence(:name) {|n| "PremiseGroup_#{n}"}
user
is_visible false
is_open false
end
factory :user do
...
end
end
Run Code Online (Sandbox Code Playgroud)
fea*_*ool 26
深入研究FactoryGirl文档,例如这个wiki页面,你会发现attribues_for忽略关联的提及.我们不想知道为什么(但我确实提交了一个问题)(但请参阅下面的更新).作为一种变通方法,我裹着一个辅助方法围绕build_attributes这条attributes_for,FactoryGirl.build(...).attributes和id:
def build_attributes(*args)
FactoryGirl.build(*args).attributes.delete_if do |k, v|
["id", "created_at", "updated_at"].member?(k)
end
end
Run Code Online (Sandbox Code Playgroud)
所以现在:
>> build_attributes(:premise_group)
=> {"name"=>"PremiseGroup_21", "user_id"=>29, "is_visible"=>false, "is_open"=>false}
Run Code Online (Sandbox Code Playgroud)
......这正是预期的结果.
吸收了FactoryGirl创建者的评论后,我理解为什么created_at忽略关联:引用关联会生成对db的调用,这会在某些情况下大大减慢测试速度.但如果您需要关联,updated_at上面显示的方法应该有效.