diff --git a/lib/rspec/core/formatters/exception_presenter.rb b/lib/rspec/core/formatters/exception_presenter.rb index 4deecda228..b649a2d687 100644 --- a/lib/rspec/core/formatters/exception_presenter.rb +++ b/lib/rspec/core/formatters/exception_presenter.rb @@ -51,7 +51,7 @@ def formatted_cause(exception) cause << '--- Caused by: ---' cause << "#{exception_class_name(last_cause)}:" unless exception_class_name(last_cause) =~ /RSpec/ - encoded_string(last_cause.message.to_s).split("\n").each do |line| + encoded_string(exception_message_string(last_cause)).split("\n").each do |line| cause << " #{line}" end @@ -174,11 +174,17 @@ def failure_slash_error_lines lines end + def exception_message_string(exception) + exception.message.to_s + rescue Exception => other + "A #{exception.class} for which `exception.message.to_s` raises #{other.class}." + end + def exception_lines @exception_lines ||= begin lines = [] lines << "#{exception_class_name}:" unless exception_class_name =~ /RSpec/ - encoded_string(exception.message.to_s).split("\n").each do |line| + encoded_string(exception_message_string(exception)).split("\n").each do |line| lines << (line.empty? ? line : " #{line}") end lines diff --git a/spec/rspec/core/formatters/exception_presenter_spec.rb b/spec/rspec/core/formatters/exception_presenter_spec.rb index 104673fa5b..ad13d84753 100644 --- a/spec/rspec/core/formatters/exception_presenter_spec.rb +++ b/spec/rspec/core/formatters/exception_presenter_spec.rb @@ -260,6 +260,26 @@ def initialize(message, backtrace = [], cause = nil) EOS end + it 'will work then the message to_s raises a looped exception' do + raising_to_s_klass = + Class.new do + def to_s + raise StandardError, self + end + end + + incorrect_message_exception = FakeException.new(raising_to_s_klass.new, []) + + the_presenter = Formatters::ExceptionPresenter.new(incorrect_message_exception, example) + + expect(the_presenter.fully_formatted(1)).to eq(<<-EOS.gsub(/^ +\|/, '')) + | + | 1) Example + | Failure/Error: Unable to find matching line from backtrace + | A #{FakeException} for which `exception.message.to_s` raises StandardError. + EOS + end + it "adds extra failure lines from the example metadata" do extra_example = example.clone failure_line = 'http://www.example.com/job_details/123'