Ruby on rails 应用程序工作,但在rSpec测试中失败

Ruby on rails 应用程序工作,但在rSpec测试中失败,ruby-on-rails,rspec,Ruby On Rails,Rspec,在用户模型中,我有以下方法: 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 pr

在用户模型中,我有以下方法:

  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"
'生成并设置新密码!'方法在应用程序中正确工作,以下是控制台中的示例:

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 > 
正如我们所看到的,它为用户提供了新的密码\u散列,因此它工作正常

我认为这是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"
正如我从这个调试输出中所看到的,用户对象只有在测试代码中显式设置了它之后才能获得它的新密码\u散列。好像是“生成并设置新密码!”方法无法更改在测试环境中创建的对象

为什么我会有如此奇怪的rSpec行为? 任何建议都是有用的

有关我的开发环境的其他一些信息:

我正在使用:

  ruby 1.8.7 (2010-01-10 patchlevel 249) [x86_64-linux]
  Rails 3.0.9
  rvm
文件片段:

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.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

为什么你要自己生成密码,而不使用类似auth gem的设备或像letmein这样更轻的东西?不要重新发明轮子。我正在使用自定义身份验证来获得更大的灵活性。is
self.save
生成和设置新密码中引发异常?不,我查过了。生成和设置新密码!方法在一切正常时返回密码。此测试中的这一行“pwd.should”证明了这一点。您能否演示如何在测试代码中创建
@user
?你是用工厂女孩制作的吗?如果是,能否显示工厂定义?您是否将
@user
的任何方法存根到其他规范中(可能会影响
@user
)?