0

Michael Hartl のチュートリアルに従って、RoR 4 アプリケーションを開発しています。

ユーザー認証テストを実装すると、すべてがうまくいきます。本よりも必須フィールドがいくつかあります。モデルは次のとおりです。

class User < ActiveRecord::Base
  before_save { self.email = email.downcase }

  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :playground_id, presence: true
  validates :default_playground_id, presence: true
  validates :active_from, presence: true
  validates :active_to, presence: true
  validates :last_name, presence: true, length: { maximum: 100 }
  validates :login, presence: true, uniqueness: true, length: { maximum: 30 }
  validates :email, presence: true, uniqueness: true, length: { maximum: 100 }, format: { with: VALID_EMAIL_REGEX }
  validates :directory_id, length: { maximum: 100 }
  validates :first_name, length: { maximum: 100 }
  validates :password_digest, length: { maximum: 100 }
  validates :remember_token, length: { maximum: 100 }
  validates :created_by, length: { maximum: 30 }
  validates :updated_by, length: { maximum: 30 }

  has_secure_password

end

認証プロセスのみに関連するテストは次のとおりです。

###USER6 to test that password is correctly managed
  describe "when password is not present" do
    before do
      @user = User.new(playground_id: 0, default_playground_id: 0, last_name: "Other User", login: "OTHER_USR", 
    email: "other@example.com", active_from: "2013-01-01", active_to: "2113-01-01", is_admin: 1.zero?,
                 password: " ", password_confirmation: " ")
    end
    it { should_not be_valid }
  end

  describe "when password doesn't match confirmation" do
    before { @user.password_confirmation = "mismatch" }
    it { should_not be_valid }
  end

  describe "with a password that's too short" do
    before { @user.password = @user.password_confirmation = "a" * 5 }
    it { should be_invalid }
  end

  describe "return value of authenticate method" do
    before { @user.save }
    let(:found_user) { User.find_by(email: @user.email) }

    describe "with valid password" do
      it { should eq found_user.authenticate(@user.password) }
    end

    describe "with invalid password" do
      let(:user_for_invalid_password) { found_user.authenticate("invalid") }

      it { should_not eq user_for_invalid_password }
      specify { expect(user_for_invalid_password).to be_false }
    end
  end

### end

はい、うまくいきます!テストを実行した結果は次のとおりです。

Failures:

  1) User model validation: with a password that's too short should be invalid
     Failure/Error: it { should be_invalid }
       expected invalid? to return true, got false
     # ./spec/models/user_spec.rb:171:in `block (3 levels) in <top (required)>'

Finished in 0.28647 seconds
37 examples, 1 failure

Failed examples:

rspec ./spec/models/user_spec.rb:171 # User model validation: with a password that's too short should be invalid

Randomized with seed 18843

ここで、User モデルにパスワードの長さの検証を追加すると、次のようになります。

...
  validates :created_by, length: { maximum: 30 }
  validates :updated_by, length: { maximum: 30 }

  has_secure_password
  validates :password, length: { minimum: 6 }

end

テストを実行すると、未定義の認証方法に関するエラーが返され、認証に関係のないテストにもブレーキがかかります。

...
  5) User model validation: return value of authenticate method with invalid password 
     Failure/Error: let(:user_for_invalid_password) { found_user.authenticate("invalid") }
     NoMethodError:

       undefined method `authenticate' for nil:NilClass

     # ./spec/models/user_spec.rb:183:in `block (4 levels) in <top (required)>'
     # ./spec/models/user_spec.rb:186:in `block (4 levels) in <top (required)>'

Finished in 0.29266 seconds

37 examples, 5 failures

Failed examples:

rspec ./spec/models/user_spec.rb:51 # User model validation: availability of mandatory fields should be valid
rspec ./spec/models/user_spec.rb:135 # User model validation: when email format is valid should be valid
rspec ./spec/models/user_spec.rb:179 # User model validation: return value of authenticate method with valid password 
...

これの理由は何ですか、どうすれば解決できますか?

ご協力いただきありがとうございます、

フレッド

PS:宝石ファイル

source 'https://rubygems.org'
ruby '2.0.0'

gem 'rails', '4.0.0'
gem 'bootstrap-sass', '2.3.2'
gem 'sass-rails',   '~> 4.0.0'
gem 'coffee-rails', '~> 4.0.0'
gem 'uglifier', '2.1.2'
gem 'bcrypt-ruby', '~> 3.0.1'
gem 'jquery-rails', '~> 3.0.4'
gem 'turbolinks', '1.3.0'
gem 'jbuilder', '1.4.2'

group :doc do
  gem 'sdoc', '0.3.20', require: false
end

# gem for dev and test only
group :development, :test do
  gem 'sqlite3', :require => 'sqlite3'
  gem 'annotate', '2.5.0'
  gem 'rspec-rails', '2.14.0'
  gem 'selenium-webdriver', '2.33.0'
  gem 'capybara', '2.1.0'
  gem 'factory_girl_rails', '4.2.0'
end
4

1 に答える 1

2

すべてのコードを見ずに言うのは難しいです。

問題はここだと思います

before { @user.save }
let(:found_user) { User.find_by(email: @user.email) }

パスワードの長さの検証を追加すると、変数@userは無効になります。これは、found_user が nil (レコードが保存されておらず、見つからない) であることを意味します。そして、あなたは得るundefined method 'authenticate' for nil:NilClass

本当に create records を使用したい場合save!create!テストで使用することをお勧めします。問題がある場合は、すぐに表示されます。

同じ理由は、認証に接続されていないが無効なレコードを DB に保存しようとする別のテストの可能性があります。

于 2013-09-07T21:06:46.780 に答える