Testing the User Model with Rspec, Devise, and Factory Girl
Asked Answered
E

3

20

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
Eggcup answered 17/5, 2011 at 14:14 Comment(0)
J
31

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)

Johnathon answered 17/5, 2011 at 14:22 Comment(6)
Unfortunately that didn't seem to work. I do want to build attributes though I think, so that I can easily manipulate @user for future tests using @user.attributes.merge(:name => "Whatever"). That's why I was trying User.create!(@user.attributes). I tried doing User.create!(@user) but it failed, this time saying that the Email was blank, and the Password was blank.Eggcup
That worked. That's very interesting. I guess what confuses me now is that I'm not sure why my other one seems to work. I have a "Role" model, and I do the same thing, using @role = Factory.build(:role), and Role.create!(@role.attributes) And it seems to pass. Interesting. Thank you sir.Eggcup
Your test here failed because of the virtual attributesJohnathon
I'm unfamiliar with the term virtual attributes. Is that related to devise?Eggcup
No at all, they are just a mean to an end: basically, you have no password_confirmation column in your model. See here for more info: railscasts.com/episodes/16-virtual-attributesJohnathon
Thanks apneadiving, I appreciate your help.Eggcup
T
9

The simplest approach IMO:

FactoryGirl.modify do
  factory :user do
    after(:build) { |u| u.password_confirmation = u.password = ... }
  end
end
Thane answered 25/4, 2013 at 18:54 Comment(0)
A
5

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.

Almita answered 4/2, 2013 at 15:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.