FactoryGirl Factory未注册 - 其他SO帖子没有注册

时间:2016-03-07 17:33:29

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

当我使用Factory Girl创建我的模型类的实例时,它会使用任何依赖工厂。所以下面打电话:

@abc = FactorGirl.create(:abc)

结果

/user/path/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.5.0/lib/factory_girl/registry.rb:24:in `find': Factory not registered: environment (ArgumentError)

我已阅读有关此错误消息的每个Stack Overflow帖子,但找不到答案。 (我甚至试过这个,记录:https://github.com/thoughtbot/factory_girl_rails/issues/120)。非常感谢任何帮助。

模型需要另一个模型:

# /app/models/abc.rb
class Abc < ActiveRecord::Base
  belongs_to :environment
  validates :environment, presence: true
end

工厂尝试创建另一个模型的实例

# /spec/factories/abcs.rb
FactoryGirl.define do
  factory :abc do
    value "MyString"
    environment FactoryGirl.create(:environment) # The offending line
  end
end

Gemfile partial:

# Gemfile
group :development, :test do
  gem 'rspec-rails'
  gem 'factory_girl_rails', :require => false
end

group :test do
  gem 'simplecov'
  gem 'shoulda-matchers'
  gem 'cucumber-rails', require: false
  gem 'database_cleaner'
end

和spec_helper.rb:

# http://stackoverflow.com/questions/21235269/method-stubbing-on-beforeall
require 'rspec/mocks/standalone'
require 'support/controller_helpers'

require 'simplecov'
SimpleCov.start

# https://www.relishapp.com/rspec/rspec-core/v/2-12/docs/example-groups/shared-examples
# https://github.com/rspec/rspec-core/issues/407
Dir["./spec/concerns/**/*.rb"].sort.each {|f| require f}

require 'factory_girl_rails'

RSpec.configure do |config|
  # Database cleaner config truncated for space

  config.include FactoryGirl::Syntax::Methods

  config.expect_with :rspec do |expectations|
    expectations.include_chain_clauses_in_custom_matcher_descriptions = true
  end

  config.mock_with :rspec do |mocks|
    mocks.verify_partial_doubles = true
  end

end

1 个答案:

答案 0 :(得分:4)

问题是您在定义之前尝试使用:environment工厂。 FactoryGirl按字母顺序加载工厂,因此工厂:abc:environment之前加载。通常这不是一个问题,因为工厂应该延迟创建对象,但是你没有延迟任何事情,并且在工厂FactoryGirl.create(:environment)被注册时你调用abc。快速而肮脏的修复 - 使此执行延迟:

environment { FactoryGirl.create(:environment) } # Note the brackets

这种方式传递块将在您实际构建新对象时执行,因此当所有工厂都已加载时。

话虽如此,你根本不需要那个街区。对于一对一关联,您可以这样做:

FactoryGirl.define do
  factory :abc do
    value "MyString"
    environment
  end
end

FactoryGirl非常聪明,可以确定它是一个关联,它是使用:environment工厂。如果您更喜欢使用不同的工厂:

FactoryGirl.define do
  factory :punk_abc do
    value "MyString"
    association :environment, factory: :bad_environment
  end
end