приложение работает, но в тесте rSpec не проходит - PullRequest
0 голосов
/ 27 декабря 2011

В пользовательской модели у меня есть следующие методы:

  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!'метод правильно работает в приложении, вот пример из консоли:

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"

Как видно из этого отладочного вывода, пользовательский объект получает свой новый password_hash ТОЛЬКО после того, как он ЯВНО был установлен в коде теста.Похоже, «генерировать_и_сет_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

Некоторые пояснения:

Я не использую заглушки@ методы пользователя в любом из моих тестов.

Я попытался сделать то же самое с 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...