为什么我在尝试创建工厂时收到此 RSpec 错误?

Why do I receive this RSpec error when I try to create a factory?

**更新*:滚动到最底部以获取最低限度的可重现错误 rails 应用程序*

我正在用 Rspec、fantaskspec gem 和 Factory Girl 测试 rails 任务。当我尝试 运行 测试时,我收到此错误:

1) update_account_reverification_table update_account_reverification_table
 Failure/Error: account = create(:account, twitter_id: 1234567890)
 NoMethodError:
   undefined method `create' for #<RSpec::ExampleGroups::UpdateAccountReverificationTable:0x007fda1bd07710>
 # ./spec/lib/tasks/account_reverification_spec.rb:18:in `block (2 levels) in <top (required)>'

在线,我的 account_reverification_spec.rb 文件中的 18 个我有这个测试。

it 'update_account_reverification_table' do
  # binding.pry
  account = create(:account, twitter_id: 1234567890)
  Account.first.reverification.twitter_reverification_sent_at.must_equal Time.now
  Account.first.reverification.twitter_reverified.must_equal true
end

我也尝试过这种变体,但测试仍然失败:

account = FactoryGirl.create(:account, twitter_id: 1234567890)

但是我收到一个不同的错误:

1) update_account_reverification_table update_account_reverification_table
 Failure/Error: account = FactoryGirl.create(:account, twitter_id: 1234567890)
 ArgumentError:
   Factory not registered: account

这是我的 spec_helper.rb 和我的 rails_helper.rb

require 'fantaskspec'
require 'factory_girl_rails'
require 'pry-rails'

RSpec.configure do |config|

  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

  config.infer_rake_task_specs_from_file_location!

end

和rails_helper.rb

ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
# Prevent database truncation if the environment is production
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'spec_helper'
require 'rspec/rails'

ActiveRecord::Migration.maintain_test_schema!

RSpec.configure do |config|
  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
  config.include FactoryGirl::Syntax::Methods
  FactoryGirl.definition_file_paths = [File.expand_path('../factories', __FILE__)]
  FactoryGirl.find_definitions
  config.fixture_path = "#{::Rails.root}/spec/fixtures"

  config.use_transactional_fixtures = true
end

请注意,我的 rails_helper.rb 文件中有这些行:

  config.include FactoryGirl::Syntax::Methods
  FactoryGirl.definition_file_paths = [File.expand_path('../factories', __FILE__)]
  FactoryGirl.find_definitions

我从之前对此处引用的不同问题的回答中抓取了这个 Specific config problem 有什么想法吗?

-----编辑#2-----

我创建了一个全新的基本示例应用程序来帮助找出可能出现此问题的位置。我已按照说明使用这些文档链接设置我的目录和树结构。

Rspec Factory Girl Rails Fantaskspec Tutorial on Rspec and Fantaskspec

目录树结构:

spec
  - factories
    - accounts.rb
  - lib
    - tasks
      - account_reverification_spec.rb
  - support
    - factory_girl.rb
  - rails_helper.rb
  - spec-helper.rb

spec/support/factory_girl.rb

的内容
RSpec.configure do |config|
  config.include FactoryGirl::Syntax::Methods
end

spec/factories/accounts.rb

的内容
FactoryGirl.define do


sequence :account_login do |n|
    "login-#{ n }"
  end

  factory :account do
    sequence :email do |n|
      "someone#{n}@gmail.com"
    end
    email_confirmation { |account| account.send :email }
    url { Faker::Internet.url }
    login { generate(:account_login) }
    password { Faker::Internet.password }
    password_confirmation { |account| account.send(:password) }
    current_password { |account| account.send(:password) }
    twitter_account 'openhub'
    name { Faker::Name.name + rand(999_999).to_s }
    about_raw { Faker::Lorem.characters(10) }
    activated_at { Time.current }
    activation_code nil
    country_code 'us'
    email_master true
    email_kudos true
    email_posts true
  end
end

spec/lib/tasks/account_reverification_spec.rb

的内容

需要'rails_helper'

RSpec.describe 'update_account_reverification_table' do
  let(:task_name) { 'update_account_reverification_table' }

  it 'correct task is called' do
    expect(subject).to be_a(Rake::Task)
    expect(subject.name).to eq("update_account_reverification_table")
    expect(subject).to eq(task)
  end

  it 'update_account_reverification_table' do
    account = create(:account, twitter_id: 1234567890)
  end
end

rails_helper.rb

的内容
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
# Prevent database truncation if the environment is production
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'spec_helper'
require 'rspec/rails'
require 'fantaskspec'

ActiveRecord::Migration.maintain_test_schema!

RSpec.configure do |config|
  Rails.application.load_tasks
  config.infer_rake_task_specs_from_file_location!
  config.fixture_path = "#{::Rails.root}/spec/fixtures"
  config.use_transactional_fixtures = true
end

spec_helper.rb

的内容
    RSpec.configure do |config|
  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

尝试将以下行添加到您的 spec_helper.rb 文件中:

require 'factory_girl'

此外,将这些行添加到您的 spec_helper.rb:

FactoryGirl.definition_file_paths.clear
FactoryGirl.definition_file_paths << File.expand_path('../factories', __FILE__)
FactoryGirl.find_definitions

并将它们从 RSpec.configure do |config| 块中删除。

此外,请确保您在正确的文件中定义了您的工厂。如果您使用 rspec.

,它应该在您的测试文件夹 (spec) 的 factories.rb 中定义

更新

FactoryGirl.definition_file_paths.clear
FactoryGirl.definition_file_paths << "./spec/factories"
FactoryGirl.find_definitions

这些行应该转到您的 spec/support/factory_girl.rb 文件并从其他任何地方删除它们。

此外,在您的 spec_helper.rb 中添加以下内容:

config.before(:all) do
  FactoryGirl.reload
end

在您的 spec_helper.rb 中,Rspec.configure 块应该如下所示:

RSpec.configure do |config|
  config.mock_with :rspec
  config.run_all_when_everything_filtered = true
  config.filter_run :focus

  config.include FactoryGirl::Syntax::Methods
end

更新

将此添加到您的 rails_helper.rb:

require_relative 'support/factory_girl.rb'

然后它应该可以工作了。