association.first使用具有has_many关联的FactoryGirl工厂在RSpec特征规范中返回nil

时间:2014-03-19 23:53:30

标签: ruby-on-rails rspec associations factory-bot

我在Rails 4应用程序中有以下内容:

FactoryGirl.define do
  factory :todo_list do
    after(:create) do |t|
      create_list(:item, 3, todo_list: t)
    end

    factory :public_todo_list do
      is_public true
    end
  end

  factory :item do
    sequence(:position) { |n| n }
    name "This is item ##{:position}?"
    todo_list
  end
end

我在功能规范中有以下内容:

feature "TodoLists" do
  let(:todo_list) { create(:public_todo_list) }

  scenario "Something that requires accessing the first item" do
    ...
    pending todo_list.items.first.name
    ...
  end
end

但是,测试失败并带有以下内容:

Failure/Error: pending todo_list.items.first.name
NoMethodError:
  undefined method `name' for nil:NilClass

由于todo_list.itemsActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_Item个对象,first似乎应该返回第一个Item记录?我得到了niltodo_list.items.count返回3test.log显示正确创建的所有记录。我错过了什么?

2 个答案:

答案 0 :(得分:2)

尝试在访问第一项之前重新加载关联:

todo_list.items.reload

我认为reload是必需的,因为todo_list对象在创建时没有任何项目,我怀疑RSpec会缓存它。 items是在创建todo_list对象后创建的。

答案 1 :(得分:1)

我在很长一段时间内没有使用过工厂语法,但它们是否继承了父工厂的回调?尝试使用特征来做这件事,这似乎对你正在做的事情更有意义。

FactoryGirl.define do
  factory :todo_list do
    after(:create) do |t|
      create_list(:item, 3, todo_list: t)
    end

    trait :public do
      is_public true
    end
  end

  factory :item do
    sequence(:position) { |n| n }
    name "This is item ##{:position}?"
    todo_list
  end
end

然后:

feature "TodoLists" do
  let(:todo_list) { create(:todo_list, :public) }

  scenario "Something that requires accessing the first item" do
    ...
    pending todo_list.items.first.name
    ...
  end
end