在用户模型中,我有以下方法:
def generate_and_set_new_password!
password = random_pronouncable_token
self.password_hash = encrypt(password)
self.password_reset_sent_at = Time.now
if self.save!
password
else
nil
end
end
private
def encrypt(string)
# Some code that encrypts string
# ...
end
def random_pronouncable_token(size = 4)
# Some code that generates new password
# ...
end
rSpec测试:
describe "New password generation" do
it "should generate new password" do
user = @user
old_pwd_hash = user.password_hash
pwd = user.generate_and_set_new_password!
pwd.should_not be_nil
user.password_hash.should_not == old_pwd_hash
end
end
这个测试给了我这样的输出:
1) User password encryption New password generation should generate new password
Failure/Error: user.password_hash.should_not == old_pwd_hash
expected not: == "966abfff742d73c71fc87a1928b90aec"
got: "966abfff742d73c71fc87a1928b90aec"
'generate_and_set_new_password! '方法在app中正常工作,这是控制台的示例:
ruby-1.8.7-p249 :014 > user.password_hash
=> "ef10fb44dfceeaca05ca78030c1d8cb5"
ruby-1.8.7-p249 :015 > user.generate_and_set_new_password!
=> "quispopeho"
ruby-1.8.7-p249 :016 > user.password_hash
=> "a0b7605d5d6ca2152f7e019b4896fef4"
ruby-1.8.7-p249 :017 >
正如我们所看到的,它为用户提供了新的password_hash,因此它可以正常工作。
我认为这是rSpec中的一些错误。我做了这样的实验:
以下是测试代码中的一些更改:
describe "New password generation" do
it "should generate new password" do
user = @user
old_pwd_hash = user.password_hash
p "old_password = ", user.password
p "old_pwd_hash = ", old_pwd_hash
pwd = user.generate_and_set_new_password!
p "received new password = #{pwd}"
p "SHOULD BE a new_pwd_hash, but it isn't! ", user.password_hash
p "SHOULD BE a new_password, but it isn't! ", user.password
pwd.should_not be_nil
# There I am tring to set this new password explicitly :)
user.password = pwd
user.save
p "NOW it is other password hash = ", user.password_hash
user.password_hash.should_not == old_pwd_hash
end
end
现在测试通过了!
调试输出如下:
"old_password = foobar"
"old_pwd_hash = c251e8a9bcc4fba1199181b1f2c1430c"
"received new password = kongibyty"
"SHOULD BE a new_pwd_hash, but it isn't! c251e8a9bcc4fba1199181b1f2c1430c"
"SHOULD BE a new_password, but it isn't! foobar"
"NOW it is other password hash = e2b53133b796bcb212a0c1fa1d2a1cfa"
正如我从这个调试输出中看到的那样,用户对象只有在测试代码中明确设置后才能获得它的新密码_hash。好像'generate_and_set_new_password!'方法无法更改在测试环境中创建的对象。
为什么我会得到如此奇怪的rSpec行为? 任何建议都会有用。
关于我的发展环境的一些其他信息:
我正在使用:
ruby 1.8.7 (2010-01-10 patchlevel 249) [x86_64-linux]
Rails 3.0.9
rvm
Gemfile片段:
group :development, :test do
gem "rspec-rails", "~> 2.6"
gem 'webrat', '0.7.1'
gem 'spork', '0.9.0.rc9'
gem 'autotest-standalone'
gem 'autotest', '4.4.6'
gem 'autotest-rails-pure', '4.1.2'
gem 'factory_girl_rails', '1.0'
end
Udpates:
创建@user
的代码require 'spec_helper'
describe User do
# attributes for user object
before(:each) do
@attr = {
:email => "user@example.com",
:password => "foobar",
:password_confirmation => "foobar",
:first_name => "Example",
:last_name => "Examploid",
:dob => Date.new(1980,07,03),
:relationships_status => "Single",
:sex => "male",
:sexual_orientaion => "Woman",
:about_me => "All about me",
:school_id => 1,
:education_id => 1,
:occupation_id => 1,
:web_site => "example.com"
}
end
# Some other tests...
# ...
describe "password encryption" do
# create user
before(:each) do
@user = User.create!(@attr)
end
# Some other tests...
# ...
# Here is shown the same test code as above.
describe "New password generation" do
it "should generate new password" do
# I even tried to use factory_girl's method
# @user = Factory(:device_user)
user = @user
old_pwd_hash = user.password_hash
pwd = user.generate_and_set_new_password!
pwd.should_not be_nil
user.password_hash.should_not == old_pwd_hash
end
end
end
end
一些澄清:
我没有在任何测试中使用@ user方法的存根。
我尝试用factory_girl做同样的事情,并且同样的测试失败了。 这里是用户的工厂定义:
Factory.define :device_user, :class => User do |user|
user.password "password"
user.password_confirmation "password"
user.email "device_user@example.com"
user.first_name "Device"
user.last_name "User"
user.dob Date.new(2011,10,03)
user.relationships_status "Single"
user.sex "male"
user.sexual_orientaion "Woman"
user.about_me "All about Device User"
user.school_id 1
user.education_id 1
user.occupation_id 1
user.web_site "device.example.com"
user.facebook_id "face_test_id"
end