回调是一个有用的解决方案,但在您添加所需的复杂层时会使测试变得困难。
另一种方法是创建一个位于用户“之上”的类。我不会争辩说这是最好的解决方案,但我发现它很有用。请注意,该类继承自User
该类:
# user_with_default_password.rb
class UserWithDefaultPassword < User
def initialize(options = {})
random_password = SecureRandom.hex(8)
options[:password] = random_password
# If creating a user with confirmation requirements
options[:password_confirmation] = random_password
# Call User.new(options)
super(options)
end
end
用法:
user = UserWithDefaultPassword.new() # => user.password = "ajfladfjkf..."
这样做的好处是您可以测试 User 和 UserWithDefaultPassword 而无需强制执行通常会减慢测试速度的回调。
此外,如果您想简单地使用User.new()
而不是UserWithDefaultPassword.new()
. 它提供了更大的灵活性和更好的测试。
更新:2014-04-21
此外,我建议将用于创建随机密码等的代码提取到一个单独的类中,您可以快速测试(无需加载 Rails 框架)。下面是我最近为执行其中一些简单任务而开设的课程。
#==================================================
# Generates random/unique strings/tokens/IDs
# See: http://ruby-doc.org/stdlib-2.0.0/libdoc/securerandom/rdoc/SecureRandom.html
# See: http://ruby.railstutorial.org/chapters/sign-in-sign-out#sec-signin_success
#==================================================
class Generator
require "securerandom"
# General-purpose encryption using SHA1 instead of bcrypt; faster but LESS SECURE than bcrypt
# (do not use for extremely sensitive data such as passwords)
def self.encrypt(value)
if value.nil? || value.empty?
""
else
Digest::SHA1.hexdigest(value.to_s)
end
end
# Although a UUID would work as an auto-generated password,
# it just seems more appropriate to make the password a random
# string.
def self.random_password
SecureRandom.urlsafe_base64(32)
end
# Used as a random, unique token
def self.uuid
SecureRandom.uuid
end
# Returns random number as string for admin 2-step authentication
def self.verification_code(length)
value = ""
if length.nil? || length.zero?
length = 6
elsif length > 20
length = 20
end
length.times do |num|
value += SecureRandom.random_number(10).to_s
end
value
end
end
用法:Generator.random_password # => "abc123..."
最大的好处是您可以在不加载 Rails 框架的情况下测试随机密码的创建,从而节省 3-4 秒的加载时间。这(大部分)通过 Rails 4.1 解决,它使用 Spring 预加载您的应用程序进行测试,但如果您不在 Rails 4.1(或使用 Spring gem)上,这是一个更好的解决方案。