ActionDispatch :: IntegrationTest抑制异常

时间:2018-02-14 13:50:29

标签: ruby-on-rails ruby ruby-on-rails-5 integration-testing actiondispatch

在调试失败的集成测试时,我一直遇到同样的问题,即我的代码中引发的异常被抑制并且未在测试输出中显示。

例如,对于以下控制器和测试:

class RegistrationController::ApplicationController
  def create
    # some code that raises an exception
  end
end
class RegistrationFlowTest < ActionDispatch::IntegrationTest

  test 'user registers successfully' do
    post sign_up_path, params: { username: 'arnold', password: '123' }
    assert_response :success  
  end

end

输出类似于

Minitest::Assertion: Expected response to be a <2XX: success>, but was a <500: Internal Server Error>

有没有办法看到确切的凸起异常?而不仅仅是HTTP响应代码的区别?

谢谢!

西蒙

2 个答案:

答案 0 :(得分:1)

我对此问题的建议方法是实际解析Rails提供的响应(至少在testdevelopment环境中默认情况下),其中包含错误的堆栈跟踪并处理错误您的测试失败的情况。这样做的好处是,当引发错误而不会导致测试失败时,它不会输出堆栈跟踪(例如,您有意测试如何处理故障的情况)。

我精心设计的这个小模块允许您调用assert_response_with_errors来断言对调用的响应,但是当响应不符合您的预期时,以可读格式输出异常消息和堆栈跟踪。 / p>

module ActionDispatch
  module Assertions
    module CustomResponseAssertions
      # Use this method when you want to assert a response body but also print the exception
      # and full stack trace to the test console.
      # Useful when you are getting errors in integration tests but don't know what they are.
      #
      # Example:
      # user_session.post create_gene_path, params: {...}
      # user_session.assert_response_with_errors :created
      def assert_response_with_errors(type, message = nil)
        assert_response(type, message)
      rescue Minitest::Assertion => e
        message = e.message
        message += "\nException message: #{@response.parsed_body[:exception]}"
        stack_trace = @response.parsed_body[:traces][:'Application Trace'].map { |line| line[:trace] }.join "\n"
        message += "\nException stack trace start"
        message += "\n#{stack_trace}"
        message += "\nException stack trace end"
        raise Minitest::Assertion, message
      end
    end
  end
end

要使用它,您需要在Rails在test_helper.rb中加载其堆栈之前将其包含在ActionDispatch :: Assertions中。所以只需将include添加到test_helper.rb中,就像这样:

ActionDispatch::Assertions.include ActionDispatch::Assertions::CustomResponseAssertions
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
...

答案 1 :(得分:0)

这是因为Rails控制器默认处理异常并提高500状态,使得异常对测试套件不可见(如果在模型的单元测试中引发错误,这将非常有用)。我们将讨论在您的测试套件中禁用此选项或其他解决方法的选项here

该链接的关键代码行,应添加到test/integration/integration_test_helper.rb

ActionController::Base.class_eval do
  def perform_action
    perform_action_without_rescue
  end
end

Dispatcher.class_eval do
  def self.failsafe_response(output, status, exception = nil)
    raise exception
  end
end
编辑:我注意到这个链接已经很老了。我对Rack非常熟悉,所以虽然第一块对我来说还不错,但我不确定第二块是否仍然是最新的。如果需要更新,您可能需要查看the relevant current Rails guide