Rails: Can't save to DB while testing rspec functions
I am using rspec to run function tests and I am unable to save the user to the DB before logging in. I am using a girl factory to create an object. fixtures are saved to db at the beginning of the test, but not removed at the end. (probably because the test failed. I don't know)
So I can't save the user before clicking on logIn and I get this error
- DECLARATION WARNING: An empty resource was provided in Devise :: Strategies :: DatabaseAuthenticatable # validate. Make sure the resource is not zero. (called from set_required_vars in app / controller / application_controller.rb: 43)
spec / features / login_to_mainpage_spec.rb (the bug persists)
require "rails_helper"
feature 'Navigating to homepage' do
let(:user) { create(:user) }
let(:login_page) { MainLoginPage.new }
scenario "login" do
login_page.visit_page.login(user)
sleep(20)
end
end
Simple page object: spec / features / pages_objects / main_login_page.rb
class MainLoginPage
include Capybara::DSL
def login(user)
fill_in 'email', with: user.email
fill_in 'password', with: "password"
click_on 'logIn'
end
def visit_page
visit '/'
self
end
end
my rails_helper
require 'spec_helper'
require 'capybara/rspec'
require 'capybara/poltergeist'
require "selenium-webdriver"
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
Dir[Rails.root.join("spec/features/page_objects/**/*.rb")].each { |f| require f }
RSpec.configure do |config|
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = false
config.before :each do
DatabaseCleaner.start
end
config.after :each do
DatabaseCleaner.clean
end
config.infer_spec_type_from_file_location!
config.include Devise::TestHelpers, :type => :controller
end
Capybara.default_driver = :selenium
Capybara.register_driver :selenium do |app|
Capybara::Selenium::Driver.new(app, :browser => :firefox)
end
in the spec helper:
require 'simplecov'
require 'factory_girl'
require 'rspec/autorun'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
ENV["RAILS_ENV"] ||= 'test'
RSpec.configure do |config|
include ActionDispatch::TestProcess
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.disable_monkey_patching!
if config.files_to_run.one?
config.default_formatter = 'doc'
end
config.profile_examples = 10
config.order = :random
Kernel.srand config.seed
end
EDIT 1
I switch the "gem" factory_girl '"to the" gem "factory_girl_rails"
and add this to application.rb
config.generators do
|g|
g.test_framework :rspec,
:fixtures => true,
:view_specs => false,
:helper_specs => false,
:routing_specs => false,
:controller_specs => true,
:request_specs => true
g.fixture_replacement :factory_girl, :dir => "spec/factories"
end
I still cannot save the user to the DB. Everything goes through but I put some sleep (10) in the code to update my DB and see te records and the user was never saved
EDIT 3
My problem is actually very simple. FactoryGirl.create never saves data to DB if I insert my rails_helper:
config.use_transactional_fixtures = true
or
config.before :each do
DatabaseCleaner.start
end
config.after :each do
DatabaseCleaner.clean
end
/ SPEC / factories
FactoryGirl.define do
factory :user do
email 'pierre@tralala.com'
password 'password'
password_confirmation 'password'
end
/spec/support/factory_girl.rb
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
end
specs / features / login_to_mainpage_spec.rb
let(:user) { create(:user) }
scenario "login" do
login_page.visit_page.login(create(:user))
sleep(5)
end
The user will not be saved due to the previously specified configuration. I need the data to be flushed between tests.
EDIT 4
If I use the console
RAILS_ENV=test rails c
FactoryGirl.create(:user) it is saved in db.
I don't understand why this doesn't work in my tests.
source to share
Try to use let!
to create your user. From rSpec documentation :
Note that let it be lazy-evaluated: it is not evaluated until the first time the method it defines is called. You can use let! force the method to be called before each example.
source to share
You said you were using FactoryGirl, but I don't see that in your test. To create my users with FactoryGirl, I always do something like this:
FactoryGirl.create(:user, password: 'test', password_confirmation: 'test', name: 'test')
If you've configured your Factory correctly, you can simply write:
FactoryGirl.create(:user)
source to share
To solve your problem with unique fields, FactoryGirl provides you with sequences:
sequence :email do |n|
"person#{n}@example.com"
end
factory :user do
email { generate(:email }
end
This will start with " person1@example.com " and add 1 to the number every time FactoryGirl.create (: user) is called.
source to share