FactoryGirl和Rspec测试中的attributes_for属性含义

43

在查看有关控制器测试的教程时,作者举了一个例子,测试了一个控制器动作的rspec测试。我的问题是,为什么他们使用attributes_for方法而不是build方法?除了它返回值的哈希之外,没有明确的解释为什么要使用attributes_for

it "redirects to the home page upon save" do
  post :create, contact: Factory.attributes_for(:contact)
  response.should redirect_to root_url
end

教程链接在此处:http://everydayrails.com/2012/04/07/testing-series-rspec-controllers.html 示例位于开始主题部分的 Controller testing basics

1个回答

73
attributes_for 将返回一个哈希表,而 build 将返回一个未持久化的对象。
考虑以下工厂:
FactoryGirl.define do
  factory :user do
    name 'John Doe'
  end
end

这是build的结果:

FactoryGirl.build :user
=> #<User id: nil, name: "John Doe", created_at: nil, updated_at: nil>

and the result of attributes_for

attributes_for的结果。
FactoryGirl.attributes_for :user
=> {:name=>"John Doe"}

我发现attributes_for对我的功能测试非常有帮助,因为我可以像下面这样创建一个用户:

post :create, user: FactoryGirl.attributes_for(:user)

使用build时,我们需要手动从user实例中创建属性哈希,并将其传递给post方法,例如:

当使用build时,我们需要手动从user实例创建属性哈希,并将其传递给post方法,例如:
u = FactoryGirl.build :user
post :create, user: u.attributes # This is actually different as it includes all the attributes, in that case updated_at & created_at

当我直接想获得对象而不是属性哈希表时,通常使用buildcreate

如果需要更多细节,请告诉我。


谢谢你,pjam。我现在明白了!在overstackflow中,你对我来说越来越像一个rspec导师了。 - thank_you
我一直在寻找这个答案。但是有一个问题...如果模型中有一些属性无法访问,我该如何绕过post :create, user: u.attributes - Adam Waite
我不确定我理解你想要什么,你是指如果某些属性不在attr_accessible列表中怎么办?那么我不明白问题在哪里,也许我在这里漏掉了什么。 - pjam
1
@AdamWaite,请查看 https://dev59.com/f3I_5IYBdhLWcg3wBuRs 中的 .except 方法,以从由 FactoryGirl 生成的哈希中删除属性。 - Anthony Panozzo
我遇到了一个错误:SyntaxError: unexpected ':', expecting end-of-input。在“post:”之后,控制台期望输入其他内容,而不是冒号。其中,“user: FactoryGirl.attributes_for(:user)”是该行代码的一部分。 - carl crott

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接