RSpec与Cookies – 即使应用程序正常工作(模拟已登录的用户),测试也会失败
我正在阅读Michael Hartl的“Ruby on Rails”Turorial“但我被困在这里。
我写了测试以检查用户编辑/更新的用户授权,我还编写了控制器代码, 它的工作原理如下:
- 如果用户未登录并尝试访问
users#edit
或users#update
则会将其重定向到登录页面 - 如果用户已登录并且他尝试编辑另一个用户,则会将其重定向到根目录
问题是在测试第2点的规范中,我检查发送PUT请求到user_path
我被重定向到root但运行rspec我得到以下错误:
Failures: 1) Authentication authorization as wrong user submitting a PUT request to users#update Failure/Error: specify { response.should redirect_to(root_url) } Expected response to be a redirect to but was a redirect to # ./spec/requests/authentication_pages_spec.rb:73:in `block (5 levels) in '
它似乎被重定向到signin_url
而不是root_url
,就像用户根本没有登录一样……这就是我猜测导致问题的原因。
应用程序在cookie中存储令牌以对用户进行身份validation。 为了测试这个,我编写了一个名为signin_user(user)
的辅助方法,并将其放在spec/support/utilities.rb
文件中:
# spec/support/utilities.rb def sign_in(user) visit signin_path fill_in "Email", with: user.email fill_in "Password", with: user.password click_button "Sign in" # Make signin work even when not using capybara (eg when using get, or post) cookies[:remember_token] = user.remember_token end
正如您所看到的那样,设置remember_token cookie以确保用户即使在使用put
, delete
等时也会被记录…或者至少它应该工作!
我怎样才能使这个规格通过呢?
# spec/requests/authentication_pages_spec.rb require 'spec_helper' describe "Authentication" do subject { page } # ... describe "authorization" do # ... describe "as wrong user" do let(:user) { FactoryGirl.create(:user) } let(:another_user) { FactoryGirl.create(:user, email: "another@example.com") } before { sign_in(user) } # ... describe "submitting a PUT request to users#update" do before { put user_path(another_user) } specify { response.should redirect_to(root_url) } end end end end
更新 :这是我的UsersController
:
class UsersController [:edit, :update] before_filter :correct_user, :only => [:edit, :update] def show @user = User.find(params[:id]) end def new @user = User.new end def create @user = User.new(params[:user]) if @user.save sign_in @user flash[:success] = "Welcome to the sample App!" redirect_to @user else render "new" end end def edit end def update if @user.update_attributes(params[:user]) sign_in(@user) flash[:success] = "Your profile was successfully updated" redirect_to @user else render "edit" end end private def signed_in_user unless signed_in? redirect_to signin_url, notice: "Please sign in to access this page." end end def correct_user @user = User.find(params[:id]) redirect_to root_url unless current_user?(@user) end end
在查看github存储库中其余代码的帮助程序后,我认为我发现了问题。
您正在使用session
变量来存储:remember_token
:
def user_from_remember_token remember_token = session[:remember_token] User.find_by_remember_token(remember_token) unless remember_token.nil? end
这本书使用cookies:
def user_from_remember_token remember_token = cookies[:remember_token] User.find_by_remember_token(remember_token) unless remember_token.nil? end
您的测试助手设置了cookie:
# Make signin work even when not using capybara (eg when using get, or post) cookies[:remember_token] = user.remember_token
但是因为你的user_from_remember_token
正在寻找session[:remember_token]
而不是cookie,它认为用户没有登录,因此测试被重定向到login_path
而不是root_path
。
它说明了为什么他们在这里使用cookie: http : //ruby.railstutorial.org/chapters/sign-in-sign-out? version = 3.2#sec: a_working_sign_in_method
如果您想继续使用会话,则需要调整测试以通过post
登录,以便put
具有会话集,例如:
describe "submitting a PUT request to users#update" do before do post sessions_path, :email => user.email, :password => user.password put user_path(another_user) end specify { response.should redirect_to(root_url) } end
谢谢你的回答! 我也正在完成这本书并遇到同样的问题。 使用会话的原因是第8.5节中的练习2是使用会话而不是cookie。
我的回答有点不同。 我的SessionsController在params中使用会话变量:
def create user = User.find_by_email(params[:session][:email]) if user && user.authenticate(params[:session][:password]) sign_in user redirect_back_or user else flash.now[:error] = 'Invalid email/password combination' render 'new' end end
所以修复稍微复杂一点:
#spec/support/utilities.rb def sign_in(user) visit signin_path fill_in "session_email", with: user.email fill_in "session_password", with: user.password click_button "Sign in" # Sign in when not using Capybara as well. post sessions_path, {:session => { :email => user.email, :password => user.password }} end
我有同样的问题,但原因不同。
我在spec / support / utilities.rb中输了一个错字
def sign_in(user) visit signin_path fill_in "Email", with: user.email fill_in "Password", with: user.password click_button "Sign in" # Sign in when not using Capybara as well cookies[:remember_toke] = user.remember_token end
请注意,最后一行显示“:remember_toke”而不是“:remember_token”
不知何故,导致测试失败并重定向到登录。
所以我在这里记录这个,以防其他人犯同样的错误。