工厂女孩传递零到用户模型

时间:2014-04-06 15:51:14

标签: ruby-on-rails-4 rspec factory-bot

非常简单,我正在使用工厂女孩来做以下事情:

FactoryGirl.define do
    sequence :user_email do |n|
        "user#{n}@example.com"
    end

    # Allows for multiple user names
    sequence :user_name do |n|
        "user#{n}"
    end

    factory :user, class: Xaaron::User do
        first_name 'Adam'
        last_name 'Something'
        user_name {generate :user_name}
        email {generate :user_email}
        password 'somePasswordThat_Is$ecure10!'
    end
end

从那里我们将这些信息传递给用户模式:

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

从那里开始,任何测试用户密码验证的测试或者看我们生成的密码是否与我们存储在数据库中的密码相同失败因为工厂女孩正在传递 nil 到数据库。

测试输出失败

  5) Xaaron::User Validation checks should validate a 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)>'

您可以在上面看到:password: nil它不应该......

生成失败的测试

it "should validate a user based on login credentials" do
  @user = FactoryGirl.create(:user)
  Xaaron::User.authenticate_user(@user.user_name, @user.password).should == @user
end

根据要求 - 架构

ActiveRecord::Schema.define(version: 20140323000123) do

  # These are extensions that must be enabled in order to support this database
  enable_extension "plpgsql"

  create_table "xaaron_users", force: true do |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

1 个答案:

答案 0 :(得分:3)

从班级attr_accessor :password中移除User。 由于ActiveRecord会将其视为虚拟属性,因此不会将其保存在数据库中。

如果您发现收到rspec失败消息:

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未保存在数据库中。请务必从attr_accessor模型中移除User,以便将password视为字段,将保存在数据库中。

接下来,您需要更新以下示例:

it "should validate a user based on login credentials" do
  @user = FactoryGirl.create(:user)
  @login_user = FactoryGirl.build(:user) 
  Xaaron::User.authenticate_user(@user.user_name, @login_user.password).should == @user 
end

@user包含在数据库中创建的实际记录,因此@user.password已经加密了密码。您的示例失败是因为您要将加密密码发送到authenticate_user方法并重新加密已加密的密码,其中包含:

BCrypt::Engine.hash_secret(password, user.salt)

实际上,对于您传递需要传递的内容的示例,实际密码没有任何加密。这就是我在您的示例中添加@login_user的原因。