Testing the User Model with Rspec, Devise, and Factory Girl

30,583

Solution 1

In Factory Girl, this create attributes:

@user_attr = Factory.attributes_for(:user)

And this create a new instance:

@user = Factory(:user)

So change the above and try:

User.create!(@user_attr)

In depth, what you're trying to do fails because:

  • you were creating a new unsaved instance

  • password is a virtual attribute

  • the attributes of the instance do not contain the virtual attributes (I guess)

Solution 2

The simplest approach IMO:

FactoryGirl.modify do
  factory :user do
    after(:build) { |u| u.password_confirmation = u.password = ... }
  end
end

Solution 3

One tip that did the work for me. I was using FactoryGirl.create(:user) which didn't work. Changed it to this:

user = FactoryGirl.build(:user)
user.password = "123456"
user.save
post :login, {:email => user.email, :password => "123456"}
# do other stuff with logged in user

This maybe is because 'password' is a virtual field. Hope this could hint someone.

Share:
30,583
ardavis
Author by

ardavis

Follower of Christ. Husband to my High School sweetheart. Computer Engineer at NASA's Kennedy Space Center. Ruby / Ruby on Rails enthusiast. B.S. in Computer Engineering from Kettering University.

Updated on July 19, 2022

Comments

  • ardavis
    ardavis almost 2 years

    I think there is a problem with my user factory being built. I'm getting an error saying that the password cannot be blank, but it's clearly set in my factories.rb. Does anyone see anything that I may be missing? Or a reason as to why the spec is failing? I do a very similar thing for one of my other models, and it seems to be successful. I'm not sure if the error is being caused by devise or not.

    Rspec Error

    User should create a new instance of a user given valid attributes
    Failure/Error: User.create!(@user.attributes)
    ActiveRecord::RecordInvalid:
      Validation failed: Password can't be blank
    # ./spec/models/user_spec.rb:28:in `block (2 levels) in <top (required)>'
    

    Factories.rb

    Factory.define :user do |user|
      user.name                   "Test User"
      user.email                  "[email protected]"
      user.password               "password"
      user.password_confirmation  "password"
    end
    

    user_spec.rb

    require 'spec_helper'
    
    describe User do
      before(:each) do
        @user = Factory.build(:user)
      end
    
      it "should create a new instance of a user given valid attributes" do
        User.create!(@user.attributes)
      end
    end
    

    user.rb

    class User < ActiveRecord::Base
      # Include default devise modules. Others available are:
      # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
      devise :database_authenticatable, :registerable,
             :recoverable, :rememberable, :trackable, :validatable
    
      # Setup accessible (or protected) attributes for your model
      attr_accessible :email, :password, :password_confirmation, :remember_me
    end