Dan Rubio
Dan Rubio

Reputation: 4897

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

**Update*: Scroll to very bottom for reproducible error in bare minimum rails app*

I am testing a rails task with Rspec, the fantaskspec gem, and the Factory Girl. When I try to run tests I receive this error:

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)>'

On line, 18 of my account_reverification_spec.rb file I have this test.

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

I have also tried this variation but the test continues to fail:

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

However I receive a different error:

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

Here is my spec_helper.rb and my 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

and 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

Note that I have these lines in my rails_helper.rb file:

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

I grabbed this from a previous answer on a different problem referenced here Specific config problem Any ideas?

-----EDIT #2------

I have created a brand new basic example app to help figure out where this problem could potentially be. I have followed the instructions to set up my directory and tree structure using these documentation links.

Rspec Factory Girl Rails Fantaskspec Tutorial on Rspec and Fantaskspec

Directory tree structure:

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

Contents of spec/support/factory_girl.rb

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

Contents of 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

Contents of spec/lib/tasks/account_reverification_spec.rb

require '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

Contents of 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

Contents of 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

Upvotes: 1

Views: 1872

Answers (1)

K M Rakibul Islam
K M Rakibul Islam

Reputation: 34338

Try adding the following line to your spec_helper.rb file:

require 'factory_girl'

Also, add these lines to your spec_helper.rb:

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

and remove them from RSpec.configure do |config| block.

Also, make sure you defined your factories in the correct file. It should be defined in factories.rb in your test folder (spec) if you use rspec.

Update

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

These lines should go to your spec/support/factory_girl.rb file and remove them from anywhere else.

Also, add the following in your spec_helper.rb:

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

In your spec_helper.rb the Rspec.configure block should look like this:

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

Update

Add this to your rails_helper.rb:

require_relative 'support/factory_girl.rb'

And then it should work.

Upvotes: 1

Related Questions