Ruby on Rails Michael Hartl 第 8.5 章测试失败 [英] Ruby on Rails Michael Hartl chapter 8.5 Test Fails

查看:47
本文介绍了Ruby on Rails Michael Hartl 第 8.5 章测试失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在另一次看到这个问题,其中 current_user 变量被定义了两次.我的代码中有同样的错误,但是删除 current_user 的第二个定义仍然无法解决我收到的错误消息.这是我在运行测试时收到的错误消息:

I've seen this question asked another time, in which the current_user variable was defined twice. I had the same error in my code, however removing the second definition of current_user still does not resolve the error message that I am receiving. This is the error message that I get when running my test:

  1) Failure:
SessionsHelperTest#test_current_user_returns_right_user_when_session_is_nil [/home/ubuntu/workspace/sample_app/test/helpers/sessions_helper_test.rb:11]:
--- expected
+++ actual
@@ -1 +1 @@
-#<User id: 762146111, name: "Michael Example", email: "michael@example.com", created_at: "2016-06-06 19:15:21", updated_at: "2016-06-06 19:15:21", password_digest: "$2a$04$LkmHj4hHVcRoTuEH6icLs.E/GebaKaY2Y/TX5nqouIj...", remember_digest: nil>
+nil

<小时>

这是我的 session_helper 文件:


This is my sessions_helper file:

module SessionsHelper
  #logs in the given user
  def log_in(user)
    session[:user_id] = user.id
  end

  #remembers a user in a persistent session
  def remember(user)
    user.remember
    cookies.permanent.signed[:user_id] = user.id
    cookies.permanent[:remember_token] = user.remember_token
  end

  #returns current logged in user
  #def current_user
    #@current_user ||= User.find_by(id: session[:user_id])
  #end

  #returns the user corresponding to the remember token
  def current_user
    if (user_id = session[:user_id])
      @current_user ||= User.find_by(id: user_id)
    elsif (user_id = cookies.signed[:user_id])
      user = User.find_by(id: user_id)
      if user && user.authenticated?(cookies[:remember_token])
        log_in user
        @current_user = user
      end
    end
  end

  def logged_in?
    !current_user.nil?
  end

  def log_out
    session.delete(:user_id)
    @current_user = nil
  end

  #forgets a persistent session
  def forget(user)
    user.forget
    cookies.delete(:user_id)
    cookies.delete(:remember_token)
  end

  #logs out the current user
  def log_out
    forget(current_user)
    session.delete(:user_id)
    @current_user = nil
  end
end   

<小时>

这是我的 users_login_test 文件:


This is my users_login_test file:

require 'test_helper'

class UsersLoginTest < ActionDispatch::IntegrationTest

  def setup
    @user = users(:michael)
  end

  test "Login with invalid information followed by logout" do
    get login_path
    post login_path, session: { email: @user.email, password: 'password' }
    assert is_logged_in?
    assert_redirected_to @user
    follow_redirect!
    assert_template 'users/show'
    assert_select "a[href=?]", login_path, count: 0
    assert_select "a[href=?]", logout_path
    assert_select "a[href=?]", user_path(@user)
    delete logout_path
    assert_not is_logged_in?
    assert_redirected_to root_url
    #simulate a user logging out in a different window
    delete logout_path
    follow_redirect!
    assert_select "a[href=?]", login_path
    assert_select "a[href=?]", logout_path,      count: 0
    assert_select "a[href=?]", user_path(@user), count: 0
  end

  test "login with remembering" do
    log_in_as(@user, remember_me: '1')
    assert_not_nil cookies['remember_token']
  end

  test "login without remembering" do
    log_in_as(@user, remember_me: '0')
    assert_nil cookies['remember_token']
  end
end

<小时>

这是我的 test_helper 文件:


This is my test_helper file:

ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'

class ActiveSupport::TestCase
  fixtures :all

  # Returns true if a test user is logged in.
  def is_logged_in?
    !session[:user_id].nil?
  end

  # Logs in a test user.
  def log_in_as(user, options = {})
    password    = options[:password]    || 'password'
    remember_me = options[:remember_me] || '1'
    if integration_test?
      post login_path, session: { email:       user.email,
                                  password:    password,
                                  remember_me: remember_me }
    else
      session[:user_id] = user.id
    end
  end

  private

    # Returns true inside an integration test.
    def integration_test?
      defined?(post_via_redirect)
    end
end

<小时>

这是我的 users.yml 文件:


This is my users.yml file:

michael:
  name: Michael Example
  email: michael@example.com
  password_digest: <%= User.digest('password') %>

<小时>

我真的不确定出了什么问题,但我想我只是错过了一些东西.任何帮助将非常感激!谢谢!


I'm really not sure whats going wrong, but I think I'm just missing something. Any help would be much appreciated! Thanks!

这是我的 user.rb 文件:

here is my user.rb file:

class User < ActiveRecord::Base
  attr_accessor :remember_token
  before_save { self.email = email.downcase }
  validates :name,  presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, length: { maximum: 255 },
                    format: { with: VALID_EMAIL_REGEX },
                    niqueness: { case_sensitive: false }
  has_secure_password
  validates :password, presence: true, length: { minimum: 6 }

  #returns the digest of a given string
  def User.digest(string)
    cost = ActiveModel::SecurePassword.min_cost ?     BCrypt::Engine::MIN_COST :
                                              BCrypt::Engine.cost
    BCrypt::Password.create(string, cost: cost)
  end

  #returns random token
  def User.new_token
    SecureRandom.urlsafe_base64
  end

  #remembers a user in the database for persistent sessions
  def remember
    self.remember_token = User.new_token
    update_attribute(:remember_token, User.digest(remember_token))
  end

  #returms true if the given token matches the digest
  def authenticated?(remember_token)
    return false if remember_digest.nil?
    BCrypt::Password.new(remember_digest).is_password?    (remember_token)
  end

  #Forgets a user
  def forget
    update_attribute(:remember_digest, nil)
  end

end

<小时>

session_helper_test.rb:


edit: sessions_helper_test.rb:

require 'test_helper'

class SessionsHelperTest < ActionView::TestCase

  def setup
    @user = users(:michael)
    remember(@user)
  end

  test "current_user returns right user when session is nil" do
    assert_equal @user, current_user
    assert is_logged_in?
  end

  test "current_user returns nil when remember digest is wrong" do
    @user.update_attribute(:remember_digest, User.digest(User.new_token))
    assert_nil current_user
  end
end

推荐答案

查看你的 session_helper.rb,#Logs out the current user 方法在文件中定义了两次.根据第 8 章中的本教程,为了运行绿色测试套件,您需要在文件中包含以下内容.

Looking at your sessions_helper.rb, the # Logs out the current user method has been defined twice in the file. According to this tutorial in ch.8, in order to run the test suite green you need following content in your file.

我认为您在清单 8.39 中搞砸了,您只需要在 log_out 方法中添加一行即可.

I think you messed this up during listing 8.39 where you just need to add one line in the log_out method.

请在 sessions_helper.rb 中填写以下代码,您的测试将变为绿色.

Please fill up the following code in the sessions_helper.rb and your tests would go green.

module SessionsHelper

  # Logs in the given user.
  def log_in(user)
    session[:user_id] = user.id
  end

  # Remembers a user in a persistent session.
  def remember(user)
    user.remember
    cookies.permanent.signed[:user_id] = user.id
    cookies.permanent[:remember_token] = user.remember_token
  end

  # Returns the user corresponding to the remember token cookie.
  def current_user
    if (user_id = session[:user_id])
      @current_user ||= User.find_by(id: user_id)
    elsif (user_id = cookies.signed[:user_id])
      user = User.find_by(id: user_id)
      if user && user.authenticated?(cookies[:remember_token])
        log_in user
        @current_user = user
      end
    end
  end

  # Returns true if the user is logged in, false otherwise.
  def logged_in?
    !current_user.nil?
  end
# Forgets a persistent session.
  def forget(user)
    user.forget
    cookies.delete(:user_id)
    cookies.delete(:remember_token)
  end

  # Logs out the current user.
  def log_out
    forget(current_user)
    session.delete(:user_id)
    @current_user = nil
  end
end

更新:同样在 app/models/user.rb 文件中,根据清单 8.45,您需要添加一行 return false if remember_digest.nil?.所以 user.rb 文件应该如下所示.

Update: Also in the app/models/user.rb file according to listing 8.45, you need to add a line return false if remember_digest.nil?. So the user.rb file should be as following.

class User < ActiveRecord::Base
  attr_accessor :remember_token
  before_save { self.email = email.downcase }
  validates :name,  presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, length: { maximum: 255 },
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
  has_secure_password
  validates :password, presence: true, length: { minimum: 6 }

  # Returns the hash digest of the given string.
  def User.digest(string)
    cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
                                                  BCrypt::Engine.cost
    BCrypt::Password.create(string, cost: cost)
  end

  # Returns a random token.
  def User.new_token
    SecureRandom.urlsafe_base64
  end

  # Remembers a user in the database for use in persistent sessions.
  def remember
    self.remember_token = User.new_token
    update_attribute(:remember_digest, User.digest(remember_token))
  end

  # Returns true if the given token matches the digest.
  def authenticated?(remember_token)
    return false if remember_digest.nil? #Add this line
    BCrypt::Password.new(remember_digest).is_password?(remember_token)
  end

  # Forgets a user.
  def forget
    update_attribute(:remember_digest, nil)
  end
end

如果您进一步遇到任何错误,请告诉我.

Please let me know if you face any error further.

这篇关于Ruby on Rails Michael Hartl 第 8.5 章测试失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆