Factory Girl Devise user factory is not valid - doesn't pass RSpec test

devise, factory-bot, rspec, ruby-on-rails

Solution

Your `email` attribute needs to be unique and you're not cleaning your database between tests, so you're getting on error on second and subsequent executions of your test. See https://relishapp.com/rspec/rspec-rails/docs/transactions to learn about use of transactions in RSpec.

Problem

I'm new to programming and have been learning Ruby on Rails for about 11 weeks. When trying to test my user factory for validation, I get ``` 1) User has a valid factory Failure/Error: expect(@user.valid?).to eq(true) expected: true got: false (compared using ==) ``` I'm using Devise for my user model, and FactoryGirl for my factories. Here is my user factory: ``` FactoryGirl.define do factory :user do name "John Fahey" sequence(:email, 100) { |n| "person#{n}@example.com" } password "password" password_confirmation "password" confirmed_at Time.now end end ``` ...and here is my spec ``` require 'rails_helper' describe User do before do @user = build(:user) end it "has a valid factory" do expect(@user.valid?).to eq(true) end end ``` I've been working on getting this spec to pass for a while now. For a while I was getting the "email already taken" error and I've gotten past that. I even got the spec to pass once, but I was using the now deprecated "should be" syntax. When I go to the correct ":expect" syntax I get this error. Does anyone have an idea of what I'm doing wrong here? Here is my model ``` class User < ActiveRecord::Base #== schema information. # create_table "users", force: true do |t| # t.string "name" # t.string "email", default: "", null: false # t.string "encrypted_password", default: "", null: false # t.string "reset_password_token" # t.datetime "reset_password_sent_at" # t.datetime "remember_created_at" # t.integer "sign_in_count", default: 0, null: false # t.datetime "current_sign_in_at" # t.datetime "last_sign_in_at" # t.string "current_sign_in_ip" # t.string "last_sign_in_ip" # t.string "confirmation_token" # t.datetime "confirmed_at" # t.datetime "confirmation_sent_at" # t.string "unconfirmed_email" # t.datetime "created_at" # t.datetime "updated_at" # end # add_index "users", ["email"], name: "index_users_on_email", unique: true # add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true has_one :list has_many :items, through: :list devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable end ``` here is what I see when I create a user instance in the rails console and test for errors: ``` 2.0.0-p576 :004 > @user = User.create (0.2ms) begin transaction (0.2ms) rollback transaction => #<User id: nil, name: nil, email: "", encrypted_password: "", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_coun t: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, confirmation_token: nil, confirmed_at: nil, confirmation_sen t_at: nil, unconfirmed_email: nil, created_at: nil, updated_at: nil> 2.0.0-p576 :005 > @user.save (1.0ms) begin transaction (0.1ms) rollback transaction => false 2.0.0-p576 :006 > puts(@user.errors) #<ActiveModel::Errors:0xa7cff88> => nil 2.0.0-p576 :007 > ``` When i print the error messages, I get ``` 2.0.0-p576 :007 > puts(@user.errors.messages) {:email=>["can't be blank"], :password=>["can't be blank"]} => nil ``` here's something interesting. Just to make sure, I did a rake db:migrate, and a rake db:test:prepare. The test passed. Then I did the exact test again, and it failed. ``` vagrant@rails-dev-box:~/code/blocitoff$ rake db:migrate vagrant@rails-dev-box:~/code/blocitoff$ rake db:migrate vagrant@rails-dev-box:~/code/blocitoff$ rake db:test:prepare vagrant@rails-dev-box:~/code/blocitoff$ rspec spec/models/user_spec.rb #<ActiveModel::Errors:0xbdf0740> . Finished in 0.1764 seconds (files took 8.96 seconds to load) 1 example, 0 failures vagrant@rails-dev-box:~/code/blocitoff$ rspec spec/models/user_spec.rb #<ActiveModel::Errors:0xa97066c> F Failures: 1) User has a valid factory Failure/Error: expect(@user.valid?).to eq(true) expected: true got: false (compared using ==) ```

Original source