FactoryGirl影响了rake db:migrate进程

32

我正在使用Ruby on Rails 3中的Rspec(2.11.0)和FactoryGirl(4.0.0)进行TDD/BDD。我有一个用于Category模型的工厂:

FactoryGirl.define "Category" do
  factory :category do
    name "Foo"
  end
end

如果我在测试环境中删除、创建然后迁移数据库,我会得到以下错误:

rake aborted!
Could not find table 'categories'
这个问题的原因是由于FactoryGirl期望表格已经存在(出于某种奇怪的原因)。如果我从我的Rails应用程序中移除spec文件夹并运行db:migrate,它就可以工作。如果我将Gemfile中的factory-girl-rails标记为:require => false也可以工作(然后我必须注释掉require才能运行rspec)。
我在这里找到了有关此问题的一些信息:https://github.com/thoughtbot/factory_girl/issues/88 我是否做错了什么?如何在db:migration任务中“绕过”FactoryGirl阶段?
4个回答

79
我认为你需要在Gemfile中定义像这样的factory girl:
  gem 'factory_girl_rails', :require => false

然后你只需要像这样在你的 spec_helper.rb 文件中 require 它:

  require 'factory_girl_rails'

这是我一直使用这个 gem 的方式。你不需要在 spec_helper.rb 以外的地方 require 它。你目前想采取的方法是错误的。


当你运行测试时,这个破坏你的rake的异常应该由rspec处理(这样它会标记规范为未通过)。你的方法是错误的,因为它不能按照你想要的方式工作。 - Vadym Chumel
我遇到了这个确切的问题,这个解决方法很有效 - 非常感谢! - Geesu
我在使用miniskirt gem时遇到了同样的问题。这个答案也可以解决miniskirt中的问题。 - Waseem
@VadimChumel,您介意解释一下为什么添加:require => false会使错误消失吗?我在存储库中找不到有关此选项的任何文档。此外,就像OP所说,添加此选项将导致运行rspec时出现错误。是否有更好的解决方案? - whales
@whales 这样修复它是因为在需要 gem 之前加载 gem 所需的文件,这恰好是 factories.rb。由于表不存在,如果工厂文件尝试加载类别类并且在加载类时如果某些内容需要存在表,则会出错。当您运行 rspec 时,可以先要求它,然后如果表存在,则应能够正确加载工厂。 - erosenin
谢谢@VadimChumel,这解决了我们在CodeShip测试环境构建中遇到的问题。 - johnpitchko

12

解决这个问题的简单方法是通过将工厂中的任何模型包装在代码块中来延迟其评估。因此,不要写成:

factory :cake do
  name "Delicious Cake"
  frosting Frosting.new(:flavor => 'chocolate')
  filling Filling.new(:flavor => 'red velvet')
end

执行此操作(注意花括号):

factory :cake do
  name "Delicious Cake in a box"
  frosting { Frosting.new(:flavor => 'chocolate') }
  filling { Filling.new(:flavor => 'red velvet') }
end

如果你有很多工厂,这可能不可行,但它相当简单。另请参见此处


谢谢,这解决了我的问题! - dahoo
我需要这个答案(尽管我也应用了有关在factory_girl Gemfile清单上设置require=false的建议。)FactoryGirl在创建表之前,在环境加载时尝试创建对象。 - LisaD
这是最终解决我的答案。 - grepsedawk

3

来源信息:http://guides.rubyonrails.org/testing.html

当您最终破坏测试数据库时(相信我,这种情况会发生),您可以根据在开发数据库中定义的规格从头开始重建它。您可以通过运行rake db:test:prepare来完成这个过程。

rake db:migrate会在开发环境上运行所有未处理的迁移,并更新db/schema.rbrake db:test:load将从当前的db/schema.rb重新创建测试数据库。在后续尝试中,最好首先运行db:test:prepare,因为它首先检查待处理的迁移并及时警告您。

rake db:test:clone            Recreate the test database from the current environment’s database schema
rake db:test:clone_structure  Recreate the test database from the development structure
rake db:test:load             Recreate the test database from the current schema.rb
rake db:test:prepare          Check for pending migrations and load the test schema
rake db:test:purge            Empty the test database.

1
你不应该需要做任何这些操作...我想问题在于你对FactoryGirl.define的参数...
尝试这个。
FactoryGirl.define do
   factory :category do
       name "Foo"
   end
end

这应该可以很好地工作,而且不会破坏我的迁移或负载..今天,我不得不解决一个问题,我直接从我的工厂引用了一个模型常量,不得不把它放在一个块中来修复问题。

FactoryGirl.define do
   factory :category do
       # this causes unknown table isseus
       # state Category::Active
       # this does not.
       state { Category::Active }
   end
end

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