工厂已注册:用户(FactoryGirl :: DuplicateDefinitionError)

48

问题描述: - 我已经安装了factory_girl_rails,但每当我尝试加载一个工厂时,它会尝试多次加载。

Environment:
- rails (3.2.1)
- factory_girl (2.5.2)
- factory_girl_rails (1.6.0)
- ruby-1.9.3-p0 [ x86_64 ]

> rake spec --trace
** Execute environment
-- Creating User Factory
-- Creating User Factory
rake aborted!
Factory already registered: user

我改变的唯一另一件事是: /config/initializers/generator.rb

Rails.application.config.generators do |g|
  g.test_framework = :rspec
  g.fixture_replacement :factory_girl
end

GEMFILE

gem 'rails', '3.2.1'

# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'

group :assets do
  gem 'sass-rails',   '~> 3.2.3'
  gem 'coffee-rails', '~> 3.2.1'

  gem 'uglifier', '>= 1.0.3'
end

gem 'jquery-rails'
gem 'devise'
gem 'haml-rails'

group :development do
  gem 'hpricot'
  gem 'ruby_parser'
  gem "rspec-rails"
end

group :test do
  gem "rspec"
  gem 'factory_girl_rails'
end

gem 'refinerycms-core',       :git => 'git://github.com/resolve/refinerycms.git'
gem 'refinerycms-dashboard',  :git => 'git://github.com/resolve/refinerycms.git'
gem 'refinerycms-images',     :git => 'git://github.com/resolve/refinerycms.git'
gem 'refinerycms-pages',      :git => 'git://github.com/resolve/refinerycms.git'
gem 'refinerycms-resources',  :git => 'git://github.com/resolve/refinerycms.git'
gem 'refinerycms-settings',   :git => 'git://github.com/resolve/refinerycms.git'

group :development, :test do
  gem 'refinerycms-testing',  :git => 'git://github.com/resolve/refinerycms.git'
end

gem 'refinerycms-inventories', :path => 'vendor/engines'

FactoryGirl.define do
  factory :role do
    title "MyString"
  end
end

这似乎是一个兼容性/环境问题,我无法解决。有什么建议吗?

编辑:这是我的spec/spec_helper.rb文件:

ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
#require 'factory_girl_rails'

# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

RSpec.configure do |config|
### Mock Framework
  #
  # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
  #
  # config.mock_with :mocha
  # config.mock_with :flexmock
  # config.mock_with :rr

  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
  #config.fixture_path = "#{::Rails.root}/spec/fixtures"

  # If you're not using ActiveRecord, or you'd prefer not to run each of your
  # examples within a transaction, remove the following line or assign false
  # instead of true.
  config.use_transactional_fixtures = true

  # If true, the base class of anonymous controllers will be inferred
  # automatically. This will be the default behavior in future versions of
  # rspec-rails.
  config.infer_base_class_for_anonymous_controllers = false
end

10
你确定没有重复的工厂吗?是否发生了不正确的复制粘贴,或是在spec/factories.rb和spec/factories/*.rb中都定义了相同的工厂? - Ineu
如果您发布您的用户工厂文件,以及您的Gemfile和spec_helper.rb文件,将会很有帮助。 - nmott
我确定我没有重复工厂。例如:在spec/factories/users.rb中,我将factory :user do更改为factory :user_random_factory_name do,它回复说“Factory already registered: user_random_factory_name”。 - user1212241
如果您有更多的信息/代码需要添加,请编辑您的问题并添加进去,就像我现在为您所做的那样。请不要编辑别人的答案来实现这一点。 - Luke Woodward
2
你是否在RubyMine中运行测试?我曾经遇到过一个问题,我的文件名掩码没有正确设置,这导致它也将我的factories.rb文件传递给rspec命令,从而创建了这个错误。 - Raf
我发现我在spec/factories/*.rbtest/factories/*.rb之间重复了。这是需要检查的一个地方。 - JellicleCat
28个回答

39

应该在 spec_helper.rb 中引用 gem factory_girl_rails,而不是在 Gemfile 中引用 - 可能是因为你重复引用了 FactoryGirl,导致出现了重复的情况。

尝试在你的 Gemfile 中使用以下代码:

group :test do
  gem "rspec"
  gem 'factory_girl_rails', :require => false
end

然后请确保在spec_helper中需要factory girl:

require 'factory_girl_rails'

顺便提一下 - 在你的Gemfile中,你不需要同时使用rspecrpsec-rails。你可以用以下内容替换它们:

group :development, :test do
  gem 'rspec-rails'
end

你需要在两个组中都使用rspec,这样rake任务在开发中才能正常工作,并且核心测试将在测试中正常工作。


没有运气。还有其他建议吗? - user1212241
我尝试从spec_helper中删除require 'factory_girl_rails',但仍然使用gem 'factory_girl_rails',:require => false接收到相同的错误消息。 - user1212241
有几件事情。你可以发布你的 spec_helper.rb 吗?另外,我的 config.generators 有以下内容 g.fixture_replacement :factory_girl, :dir => 'spec/factories',你可能想尝试一下。另外,你不需要 g.test_framework = :rspec,因为当安装了 rspec 时,它会在 Rails 中注册自己,所以你不需要显式调用它。 - nmott
我已经更新了我的原始帖子,并附上了我的spec_helper.rb文件。非常感谢您能提供的任何帮助! - user1212241
只要你按照我上面说的做,那么你的 gem 和 spec_helper 文件看起来都没问题。你能发一下你的 factory 文件吗?或许你应该尝试移除生成器 - 在这个问题解决之前可以不用它们。 - nmott
你能发布你的工厂文件吗? - nmott

25

我最近也遇到了同样的问题。在我的情况下,位于 /factories 目录中的一个文件以 _spec.rb 结尾(由 creative cp 使用造成)。它被加载了两次,首先是由 rspec 加载,然后作为一个工厂。


我也遇到了这个问题。在很长一段时间里,我都找不到答案,直到最终发现它是问题的根源。 - Kieran Andrews
是的,这也是我的失误。 - Yahor Zhylinski
在我的情况下,我正在使用单个文件运行rspec,但是使用工厂文件路径(rspec/factories/myfile.rb)而不是模型文件路径(spec/models/myfile_spec.rb)。 - gl3yn
哈哈哈,我也一样,在改代码上花了将近两个小时,但结果还是一样。最后我在控制台里搜索了这个错误信息并找到了这个答案!🤦‍♂️ - alexventuraio

16

你是否有把这整个片段从配置文档复制到支持文件中的机会?

# RSpec
# spec/support/factory_girl.rb
RSpec.configure do |config|
  config.include FactoryGirl::Syntax::Methods
end

# RSpec without Rails
RSpec.configure do |config|
  config.include FactoryGirl::Syntax::Methods

  config.before(:suite) do
    FactoryGirl.find_definitions
  end
end

如果你看了评论,你会发现你只需要选择一个代码块。我曾犯过这个错误,也遇到了问题中提到的错误。


1
是的。这也不是我第一次这样做了。真丢人。 - Andy Copley
是的,我也做到了。#我们中的一员 - Jay Killeen
这对我解决了问题。谢谢! - Andrés Mejía
是的,那些文档需要修正,太容易就把它放进去了。我会为此创建一个PR。 - Jarvis Johnson

15

我也遇到了这个问题。在我的情况下,有两个文件的代码相同,像这样:

FactoryGirl.define do
  factory :user do
  end
end

其中一个文件名为"Useres.rb",另一个为"User.rb",因此我只删除了"Useres.rb"并修复了错误。


11

调用FactoryGirl.define(:user)FactoryGirl.find_definitions两次可能会导致此问题。

尝试删除第二个调用,或者:

FactoryGirl.factories.clear
FactoryGirl.find_definitions  

9
另一个可能的原因是多余调用FactoryGirl.find_definitions。如果找到了,请尝试删除find_definitions。

1
我之前也遇到了同样的问题,但现在已经解决了。 - Frank Riccobono
这为我解决了问题 :) - ChuckJHardy
我在/support/factory_girl.rb中有这个代码FactoryGirl.find_definitions - https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#rspec 并且有一个注释说 - rspec没有rails,复制粘贴错误 :) - rmagnum2002

6

请确保您的个人工厂文件不以_spec结尾。


我有一个名为"standard_spec"的模型。我将工厂文件重命名为standard_spec_factory.rb,一切都正常了。显而易见,但我之前没有想到。谢谢@scarver2。 - rude-n8
*_type.rb 后缀是 Ruby 社区采用的一种惯例。每当 RSpec 测试套件运行时,它会测试所有以 _spec.rb 结尾的文件。这个模糊的问题是他有一个以 _spec.rb 命名结尾的工厂文件,而 RSpec 尝试将其处理为一个规范文件。按照约定,将所有工厂命名为后缀 _factory.rb 表示该文件是一个工厂文件,而不是一个规范文件,从而被 RSpec 处理器忽略。 - scarver2

2
将Factory Girl加载到开发控制台中也会出现这种情况:

https://github.com/thoughtbot/factory_girl/issues/638


注:Factory Girl是一个用于测试的库。

require 'factory_girl_rails'; reload!; FactoryGirl.factories.clear; FactoryGirl.find_definitions

在Factory Girl v4.4.0版本下,如果一个序列重复会引发FactoryGirl::DuplicateDefinitionError错误。

似乎在FG中处理序列的方式有所不同,将所有序列包装在rescue块中即可解决该问题。

例如:

  begin
    sequence :a_sequence do |n|
      n
    end
    sequence :another_sequence do |n|
      n*2
    end
  rescue FactoryGirl::DuplicateDefinitionError => e
    warn "#{e.message}"
  end

1
我曾经遇到完全相同的问题。 这种情况发生在使用脚手架生成器时。 它会自动在test/factories/中创建一个工厂。 通常只需删除此文件即可解决您的问题。

1
我遇到了同样的问题,原来是在 test/factories 目录下创建了一个默认的 users.rb 文件,这个文件是通过 rails g 命令创建的。这个文件导致了冲突。当我删除了这个文件时,错误就消失了。

1
rails generate model <my-model> 也对我造成了问题,因为我正在使用 rspec。谢谢! - Dylan Pierce

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