Rails rspec 测试中编辑 factorygirl 生成的对象的疑惑

ane · 2014年05月01日 · 最后由 wikimo 回复于 2014年05月01日 · 2900 次阅读

各位大大,测试是选择 rails Tutorial.

先上测试代码

describe "edit" do
    let(:user) { FactoryGirl.create(:user) }
    before { visit edit_user_path(user) }
    describe "page" do
      it { should have_content("Update your profile") }
      it { should have_title("Edit user") }
      it { should have_link('change', href: 'http://gravatar.com/emails') }
    end

在上 controller

def edit
  @user = User.find(params[:id])
end

测试是通过的。只是我的疑惑是这样的。测试中的let(:user) { FactoryGirl.create(:user) }创建了一个 user 对象 (我是觉得它没有 id 的)。这样调用visit edit_user_path(user)的话,显然不可能生成..user/:id/edit这样的 url(因为 user 中我觉得没有 id)

但是:事实是测试通过的,所以想必FactoryGirl.create(:user)是生成了 id。熟悉 FactoryGirl 的给解答一下吧,先谢谢了。

PS: 看到 FactoryGirl,我就想起早年有个段子。“who create the table girl,and I should wirte the sql like "insert into girl ...."”

疑问在哪?

tailf log/test.log

或者干脆 let(:user) { u=FactoryGirl.create(:user); puts u.new_record?; u }

用一个库/框架的时候先把文档读完比较好,或者像上面这样动手试。不好用猜的

# Returns a User instance that's not saved
user = build(:user)

# Returns a saved User instance
user = create(:user)

# Returns a hash of attributes that can be used to build a User instance
attrs = attributes_for(:user)

# Returns an object with all defined attributes stubbed out
stub = build_stubbed(:user)

# Passing a block to any of the methods above will yield the return object
create(:user) do |user|
  user.posts.create(attributes_for(:post))
end

我是直接再 test 代码里 puts 的,快又准

#3 楼 @xds2000 puts 带来光明。失去了 puts,生活会怎样?

#1 楼 @Rei 疑问就是 edit_user_path(FactoryGirl.create(:user)) 这样 ok 吗?生成的 user 有 id 属性吗

#2 楼 @yuan 谢谢你的回答,我觉得对我很有帮助,只是我该用了 p u,效果比你的好点。文档是以后要一定读的,

create 没问题吧?打印下就知道了,build 就有问题了。

create 应该是吧数据插到表里的 你可以 create 后 User.first 看看

这个确实是生成了 persisted record 的。FactoryGirl.create直接呼叫 model 的 create,生成正常的记录。但build_stubbed就不会。在 controller 测试中用create是正确的。

let是懒方法,不叫不动的。因为你在edit_user_path(user)里面叫了它,所以记录生成了,测试通过。

let有时要注意的。这个测试没有问题,但你如果测试index, 前面用了let(:user){FactoryGirl.create :users, 5)}, 后面就会通不过,因为你不呼叫记录就不能生成。这时就要用let!强制生成。

这里定义了 user,FactoryGirl.create(:user) 按照它创建的,它当然是有数据库 ID 的。

FactoryGirl.define do
  factory :admin, class: User do
    email '[email protected]'
    password '123456'
    password_confirmation '123456'
  end

  factory :user do
    email '[email protected]'
    password '123456'
    password_confirmation '123456'
    factory :user_with_orders do
      ignore do
        orders_count 5
      end

      after(:create) do |user, evaluator|
        create_list(:order, evaluator.posts_count, user: user)
      end
    end
  end
end

最简单的方法是 p 一下它,比如

describe "with user's address" do
      let(:user_address) { FactoryGirl.create(:address) }
      p user_address

id 属性是自动添加的啊,任何框架都这样。你 factory.create 和程序里 create 进行的操作是一样。你程序里 create 的时候,也会指明 id 吗?

需要 登录 后方可回复, 如果你还没有账号请 注册新账号