ruby on rails 4 - Factory Girl Passing nil to user model -
pretty simple, using factory girl following:
factorygirl.define sequence :user_email |n| "user#{n}@example.com" end # allows multiple user names sequence :user_name |n| "user#{n}" end factory :user, class: xaaron::user first_name 'adam' last_name 'something' user_name {generate :user_name} email {generate :user_email} password 'somepasswordthat_is$ecure10!' end end
and there pass information user modal:
require 'bcrypt' module xaaron class user < activerecord::base attr_accessor :password before_save :encrypt_password validates :first_name, presence: true validates :user_name, uniqueness: true, presence: true, length: {minimum: 5} validates_format_of :email, :with => /\a([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i validates_uniqueness_of :user_name validates_uniqueness_of :email validates :password, presence: true, confirmation: true, length: { minimum: 10 }, if: :new_record? def self.authenticate_user(user_name, password) user = xaaron::user.find_by_user_name(user_name) if(user && user.password == bcrypt::engine.hash_secret(password, user.salt)) user else nil end end def encrypt_password if password.present? self.salt = bcrypt::engine.generate_salt self.password = bcrypt::engine.hash_secret(password, salt) end end end end
from there, test tests user password validation or seeing if password generate same 1 store in database fails because factory girl passing nil database.
failed test output
5) xaaron::user validation checks should validate user based on login credentials failure/error: xaaron::user.authenticate_user(@user.user_name, @user.password).should == @user expected: #<xaaron::user id: 5, first_name: "adam", last_name: "something", user_name: "user9", email: "user8@example.com", password: nil, salt: "$2a$10$y1m4yk.4znwvz2icp0ento", created_at: "2014-04-06 15:20:53", updated_at: "2014-04-06 15:20:53"> got: nil (using ==) # ./spec/models/xaaron/user_spec.rb:33:in `block (3 levels) in <top (required)>'
you can see in above that: password: nil
shouldn't ...
the test generated fail
it "should validate user based on login credentials" @user = factorygirl.create(:user) xaaron::user.authenticate_user(@user.user_name, @user.password).should == @user end
as requested - schema
activerecord::schema.define(version: 20140323000123) # these extensions must enabled in order support database enable_extension "plpgsql" create_table "xaaron_users", force: true |t| t.string "first_name" t.string "last_name" t.string "user_name" t.string "email" t.string "password" t.string "salt" t.datetime "created_at" t.datetime "updated_at" end end
remove attr_accessor :password
class user
. activerecord treat virtual attribute , not saved in database.
if notice rspec failure message received:
expected: #<xaaron::user id: 5, first_name: "adam", last_name: "something", user_name: "user9", email: "user8@example.com", password: nil, salt: "$2a$10$y1m4yk.4znwvz2icp0ento", created_at: "2014-04-06 15:20:53", updated_at: "2014-04-06 15:20:53">
password
not saved in database. make sure remove attr_accessor
user
model password
treated field , would saved in database.
next, need update example below:
it "should validate user based on login credentials" @user = factorygirl.create(:user) @login_user = factorygirl.build(:user) xaaron::user.authenticate_user(@user.user_name, @login_user.password).should == @user end
@user
contains actual record created in database, @user.password
has encrypted password already. example fails because sending encrypted password authenticate_user
method , re-encrypting encrypted password with:
bcrypt::engine.hash_secret(password, user.salt)
in reality, example pass need pass actual password without encryption. why added @login_user
in example.
Comments
Post a Comment