我正在学习第9课的登录,但是登录测试就是不能通过!我严格遵循代码,但它仍然不能通过。
使用浏览器进行测试时-登录工作正常,没有错误。
失败:
1)应使用有效的电子邮件和密码创建POST 'create‘,并在失败时对用户进行签名/Error: controller.current_user.should == @user expected:# got: nil (using ==) # `block ``block (4 levels) in’
2)使用有效电子邮件和密码的SessionsController POST 'create‘应重定向到用户显示页面失败/错误: response.should redirect_to(user_path(@ user ))预期块返回真值。# ./spec/controllers/sessions_controller_spec.rb:61:in ` `block (4 levels) in‘
5.12秒内完成7例,2次失败
失败示例:
rspec ./spec/controllers/sessions_controller_spec.rb:53 # SessionsController POST 'create' with valid email and password should sign the user in
rspec ./spec/controllers/sessions_controller_spec.rb:59 # SessionsController POST 'create' with valid email and password should redirect to the user show page如您所见,由于某种原因,测试controller.current_user.should == @user返回nil。
请帮助我理解这一点..
谢谢
SessionHelper
module SessionsHelper
def sign_in(user)
cookies.permanent.signed[:remember_token] = [user.id, user.salt]
self.current_user= user
end
def signed_in?
!self.current_user.nil?
end
def current_user=(user)
@current_user = user
end
def current_user
@current_user ||= user_from_remember_token
end
private
def user_from_remember_token
User.authenticate_with_salt(*remember_token)
end
def remember_token
cookies.signed[:remember_token] || [nil, nil]
end
end会话控制器
class SessionsController < ApplicationController
def new
@title = "Sign In"
end
def create
user = User.authenticate(params[:session][:email], params[:session][:password])
if user.nil?
flash.now[:error] = "Invalid email/password"
@title = "Sign In (right this time)"
render 'new'
else
#sign in the user
sign_in @user
redirect_to user
end
end
def destroy
end
end用户模型
require 'digest'
class User < ActiveRecord::Base
attr_accessor :password
attr_accessible :name, :email, :password, :password_confirmation
email_regex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :name, :presence => true,
:length => {:minimum => 2, :maximum => 50}
validates :email, :presence => true, :format => {:with => email_regex}, :uniqueness => {:case_sensitive => false }
#Automatically creates the virtual password confimration attribute
validates :password, :presence => true,
:confirmation => true,
:length => {:within => 6..40}
before_save :encrypt_password
def has_password?(submitted_password)
self.salt = make_salt if new_record?
encrypted_password == encrypt(submitted_password)
end
def self.authenticate(email, submitted_password)
user = find_by_email(email)
return nil if user.nil?
return nil if user.has_password?(submitted_password)
end
def self.authenticate_with_salt(id, cookie_salt)
user = find_by_id(id)
(user && user.salt == cookie_salt) ? user : nil
end
private
def encrypt_password
self.salt = make_salt unless has_password?(password)
self.encrypted_password = encrypt(password)
end
def encrypt(string)
secure_hash("#{salt}--#{string}")
end
def make_salt
secure_hash("#{Time.now.utc}--#{password}")
end
def secure_hash(string)
Digest::SHA2.hexdigest(string)
end
end会话控制器规范
require 'spec_helper'
describe SessionsController do
render_views
describe "GET 'new'" do
it "should be successful" do
get 'new'
response.should be_success
end
it "should have the right title" do
get :new
response.should have_selector("title", :content => "Sign In")
end
end
describe "POST 'create'" do
describe "invalid login" do
before(:each) do
@attr = {:email => "email@example.com", :password => "invalid"}
end
it "should re-render the new page" do
post :create, :session => @attr
response.should render_template('new')
end
it "should have the right title" do
post :create, :session => @attr
response.should have_selector("title", :content => "Sign In (right this time)")
end
it "should have flash.now message" do
post :create, :session => @attr
flash.now[:error].should =~ /invalid/i
end
end
describe "success" do
before(:each) do
@user = Factory(:user)
@attr = { :email => @user.email, :password => @user.password }
end
it "should sign the user in" do
post :create, :session => @attr
controller.current_user.should == @user
controller.should be_signed_in
end
it "should redirect to the user show page" do
post :create, :session => @attr
response.should redirect_to(user_path(@user))
end
end
end
end发布于 2011-09-30 18:36:06
我假设您已经完成了9.3.3节,并将authenticate类方法添加到您的用户模型中。
如果您检查您的身份验证(9.17)类方法,它具有user = find_by_email(email)。您应该首先检查您的工厂是否确实在测试数据库中创建了一个用户。
更新
这个在SessionsHelper有吗?
def signed_in?
!current_user.nil?
end更新2
删除SessionsHelper中的以下内容!!
def current_user=(user)
@current_user = user
endHartl非常具体地说明了为什么要删除这个编写器
如果我们这样做,我们将有效地复制attr_accessor的功能,该功能在4.4.5节中首次出现,并在7.1.1.7节中用于创建虚拟密码属性。问题是它完全不能解决我们的问题:使用清单9.15中的代码,用户的登录状态将被遗忘:一旦用户转到另一个页面--the会话将结束,用户将自动注销。
为了避免这个问题,我们可以找到与清单9.12中的代码创建的cookie相对应的会话用户,如清单9.16所示。
它将被替换为
def current_user
@current_user ||= user_from_remember_token
end首先,清单9.16使用了常见但最初模糊的||= (“or
”)赋值运算符(方框9.4)。它的作用是将@current_user实例变量设置为与记忆标记对应的用户,但仅当@current_user未定义时。8换句话说,该构造在第一次调用current_user时调用user_from_remember_token方法,但在随后的调用中返回@current_user,而不调用user_from_remember_token。
发布于 2011-10-18 06:40:42
我也有同样的问题。我也理解它应该被替换。但它不应该both methods are needed。
def current_user=(user)
@current_user = user
end
def current_user
@current_user ||= user_from_remember_token
end 发布于 2012-07-28 14:15:39
我花了很长时间才找到这个人...
rspec错误消息:
1) SessionsController POST 'create' with valid email and password should sign the user in
Failure/Error: controller.current_user.should == @user
NoMethodError:
undefined method `current_user' for #<SessionsController:0x00000005426eb8>
# ./spec/controllers/sessions_controller_spec.rb:51:in `block (4 levels) in <top (required)>'您想要编辑app/helpers/sessions_helper.rb:
错误:
def current_user=(user)
@current_user = user ||= user_from_remember_token
end右图:
def current_user
@current_user ||= user_from_remember_token
end很明显,在我跟随本文的过程中,我没有给予足够的关注,不幸的是,来自rspec的错误消息并没有像通常那样有帮助。希望这能有所帮助!
https://stackoverflow.com/questions/7608499
复制相似问题