如何使config.exceptions_app与rspec一起工作

时间:2013-08-27 04:48:14

标签: ruby-on-rails-3.2 rspec2 rails-routing custom-exceptions

在我的Rails 3.2应用程序中,我正在尝试使用config.exceptions_app通过路由表路由异常以呈现特定于错误的页面(尤其是401 Forbidden页面)。这是我到目前为止配置的内容:

# application.rb
config.action_dispatch.rescue_responses.merge!('Error::Forbidden' => :forbidden)
config.exceptions_app = ->(env) { ErrorsController.action(:show).call(env) }

# development.rb
config.consider_all_requests_local       = false

# test.rb
config.consider_all_requests_local       = false

现在问题的关键是:

module Error
  class Forbidden < StandardError
  end
end

class ErrorsController < ApplicationController
  layout 'error'

  def show
    exception       = env['action_dispatch.exception']
    status_code     = ActionDispatch::ExceptionWrapper.new(env, exception).status_code
    rescue_response = ActionDispatch::ExceptionWrapper.rescue_responses[exception.class.name]

    render :action => rescue_response, :status => status_code, :formats => [:html]
  end

  def forbidden
    render :status => :forbidden, :formats => [:html]
  end
end

当我想呈现401响应时,我只是raise Error::Forbidden,它在开发环境中完美运行。但是当在rspec中运行一个例子时,例如:

it 'should return http forbidden' do
  put :update, :id => 12342343343
  response.should be_forbidden
end
它悲惨地失败了:

1) UsersController PUT update when attempting to edit another record should return http forbidden
   Failure/Error: put :update, :id => 12342343343
   Error::Forbidden:
     Error::Forbidden

有人可以帮助我理解为什么这在我的测试环境中不起作用?我可以在ApplicationController中放置一个#rescue_from,但是如果我必须这样做才能让我的测试工作,我不确定使用config.exceptions_app的重点是什么。 : - \

编辑:作为一种解决方法,我最后在config / environments / test.rb结尾处放了以下内容这很糟糕,但似乎工作正常。

module Error
  def self.included(base)
    _not_found = -> do
      render :status => :not_found, :text => 'not found'
    end

    _forbidden = -> do
      render :status => :forbidden, :text => 'forbidden'
    end

    base.class_eval do
      rescue_from 'ActiveRecord::RecordNotFound', :with => _not_found
      rescue_from 'ActionController::UnknownController', :with => _not_found
      rescue_from 'AbstractController::ActionNotFound', :with => _not_found
      rescue_from 'ActionController::RoutingError', :with => _not_found
      rescue_from 'Error::Forbidden', :with => _forbidden
    end
  end
end

2 个答案:

答案 0 :(得分:2)

config/environments/test.rb集合中:

config.action_dispatch.show_exceptions = true

答案 1 :(得分:0)

我有同样的问题。提出异常的地方要小心。如果它位于before_filter / before_action中,则会吞下您的例外情况。将您的取景器代码移动到实际方法,您的例外应显示在您的规范中。