【问题标题】:Failure/Error: specify { expect(response).to redirect_to(root_url) }失败/错误:指定 { expect(response).to redirect_to(root_url) }
【发布时间】:2016-10-09 11:49:06
【问题描述】:

我不明白,为什么不通过测试,它执行第一个重定向而不是第二个,正如控制器代码本身所描述的那样正常工作,重定向完全按照描述发生。

Rspec 3.5.1

轨道 5

Ruby 2.3.1

spec/features/authentication_pages_spec.rb

describe "autorization", type: :request do

    describe "for non-signed-in users" do
        let(:user) { FactoryGirl.create(:user) }

        describe "in the Users controller" do

            describe "visiting the edit page" do
                before { visit edit_user_path(user) }
                it { should have_title('Log in') }
            end

            describe "submitting to the update action" do
                before { patch user_path(user) }
                specify { expect(response).to redirect_to(login_path) }
            end
        end
    end

    describe "as wrong user" do
        let(:user) { FactoryGirl.create(:user) }
        let(:wrong_user) { FactoryGirl.create(:user, email: "wrong@example.com") }
        before { log_in user, no_capybara: true }

        describe "submitting a GET request to the Users#edit action" do
            before { get edit_user_path(wrong_user) }
            specify { expect(response.body).not_to match(full_title('Edit user')) }
            specify { expect(response).to redirect_to(root_url) }
        end

        describe "submitting a PATCH request to the User#update action" do
            before { patch user_path(wrong_user) }
            specify { expect(response).to redirect_to(root_url) }
        end
    end
end
end

测试失败并出现以下错误:

1) AuthenticationPages 授权错误用户向 Users#edit 操作提交 GET 请求应重定向到“http://www.example.com/” 失败/错误:指定 { expect(response).to redirect_to(root_url) }

   Expected response to be a redirect to <http://www.example.com/> but was a redirect to <http://www.example.com/login>.
   Expected "http://www.example.com/" to be === "http://www.example.com/login".

2) AuthenticationPages 授权错误用户向 User#update 操作提交 PATCH 请求应重定向到“http://www.example.com/” 失败/错误:指定 { expect(response).to redirect_to(root_url) }

   Expected response to be a redirect to <http://www.example.com/> but was a redirect to <http://www.example.com/login>.
   Expected "http://www.example.com/" to be === "http://www.example.com/login".

当它应该重定向到根 url 时,我无法理解为什么它会重定向到登录 url - 用户在规范中登录。

这是用户控制器:

class UsersController < ApplicationController
  before_action :logged_in_user, only: [:edit, :update]
  before_action :correct_user,   only: [:edit, :update]


def show
    @user = User.find(params[:id])      
end

def new
    @user = User.new
end

def create
    @user = User.new(user_params)
    if @user.save
     log_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(user_params)
    flash[:success] = "Profile updated"
    redirect_to @user
  else
    render 'edit'
  end
end

private

def user_params
    params.require(:user).permit(:name, :email, :password, :password_confirmation)
end

# Before filters

def logged_in_user
  unless logged_in?
    flash[:danger] = "Please log in."
    redirect_to login_url
  end
end

def correct_user
  @user = User.find(params[:id])
  redirect_to(root_url) unless current_user?(@user)
end
end

以下是我的 sessions_helper.rb 文件的相关位:

module SessionsHelper

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

# Returns the current logged-in user (if any).
def current_user
  remember_token = User.encrypt(cookies[:remember_token])
  @current_user ||= User.find_by(id: session[:user_id])
end

def current_user?(user)
  user == current_user
end

# Returns true if the user is logged in, false otherwise.
def logged_in?
  !current_user.nil?
end

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

用户类别:

class User < ApplicationRecord
  has_secure_password
  before_save { self.email = email.downcase }
  before_create :create_remember_token
  validates :name, presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+(\.[a-z]+)*\.[a-z]+\z/i
  validates :email, presence: true, format: { with: VALID_EMAIL_REGEX     },uniqueness: { case_sensitive: false }
  validates :password, length: { minimum: 6 }

  def User.new_remember_token
      SecureRandom.urlsafe_base64
  end

  def User.encrypt(token)
      Digest::SHA1.hexdigest(token.to_s)
  end

  private

  def create_remember_token
      self.remember_token = User.encrypt(User.new_remember_token)
  end
 end

spec/support/utilities.rb

include ApplicationHelper

def valid_login(user)
  fill_in "Email",    with: user.email
  fill_in "Password", with: user.password
  click_button "Log in"
end

RSpec::Matchers.define :have_error_message do |message|
  match do |page|
    expect(page).to have_selector('div.alert.alert-error', text:   message)
  end
end

def log_in(user, options={})
    if options[:no_capybara]
        # Sign in when not using Capybara.
        remember_token = User.new_remember_token
        cookies[:remember_token] = remember_token
        user.update_attribute(:remember_token,       User.encrypt(remember_token))
    else
        visit login_path
        fill_in "Email",        with: user.email
        fill_in "Password",     with: user.password
        click_button "Log in"   
    end
end

【问题讨论】:

  • 您的规范中使用的log_in 方法的代码是什么?
  • 这会创建一个与默认电子邮件地址不同的用户。测试指定原始用户不应有权访问错误用户的编辑或更新操作。
  • 您可以在问题中包含该代码吗?我认为这是相关的。
  • 他是第一个去

标签: ruby-on-rails rspec rubygems rspec-rails rspec3


【解决方案1】:

我怀疑您的问题与

有关
before { log_in user, no_capybara: true }

试试改成

before { session[:user_id] = user.id }

【讨论】:

  • 此解决方案不起作用,没有会话方法。更改后出现错误Failure/Error: before { session[:user_id] = user.id } NoMethodError: undefined method session' for nil:NilClass `
  • 对不起,我错误地认为这是一个控制器测试。我对登录用户部分有点困惑......我认为 SessionsHelper 是您应用程序的一部分。在这种情况下,log_in 是如何路由到它的?
  • 如果我理解正确的话,是这样的:get /login, to: sessions#new post /login, to: sessions#create
  • 好吧,从你的代码中我仍然不清楚 before 块中的 log_in user 实际调用了什么?我假设您必须有一个具有此方法的支持类 - 我并不是说 SessionsHelper 因为它似乎是您的应用程序控制器的助手。我确实怀疑这是您的问题所在 - 尝试测试 expect(request.session[:user_id]).to eq(user.id) 以查看用户是否实际登录。
  • 添加了规范/支持/实用程序.rb
【解决方案2】:

问题在于您的 log_in 方法(在规范中,而不是帮助代码),它实际上并没有让任何人登录。这就是您遇到登录错误的原因。您提到此代码“创建一个与默认电子邮件地址不同的用户”,但这不是它应该做的;它应该设置会话。

简单地创建用户不会设置会话,如果没有设置会话,logged_in? 将为 false,您将被重定向到登录页面。

试试这样的:

before { @request.session[:user_id] = user.id }

这会在对用户 ID 的请求上显式设置会话,以便 logged_in? 将在您的控制器中返回 true

【讨论】:

  • 会话方法中的错误,我做什么,我按照 Michael Hartl 的书做的
猜你喜欢
  • 1970-01-01
  • 2021-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-13
相关资源
最近更新 更多