diff --git a/lib/rspec/matchers/built_in/raise_error.rb b/lib/rspec/matchers/built_in/raise_error.rb index a347ed3a9..c56260d02 100644 --- a/lib/rspec/matchers/built_in/raise_error.rb +++ b/lib/rspec/matchers/built_in/raise_error.rb @@ -238,10 +238,10 @@ def given_error return " but nothing was raised" unless @actual_error backtrace = format_backtrace(@actual_error.backtrace) - [ - ", got #{description_of(@actual_error)} with backtrace:", - *backtrace - ].join("\n # ") + + ", got #{description_of(@actual_error)}" + + error_message_text + + text_with_indent(" with backtrace:", backtrace) end def expecting_specific_exception? @@ -257,6 +257,25 @@ def warning warning = "Actual error raised was #{description_of(@actual_error)}. " warning if @actual_error end + + private + + def error_message_text + return '' if @actual_error.message.nil? || @actual_error.message.empty? + return '' if @actual_error.message == @actual_error.class.to_s + + text_with_indent(" with message:", @actual_error.message.split(/\n/)) + + "\nand" + end + + INDENT = ["\n # ".freeze].freeze + + def text_with_indent(prefix, text_lines) + text_lines = Array(text_lines) + message_text = [prefix] + message_text += ([INDENT] * text_lines.size).zip(text_lines) + message_text.join + end end # rubocop:enable RescueException # rubocop:enable ClassLength diff --git a/spec/rspec/matchers/built_in/raise_error_spec.rb b/spec/rspec/matchers/built_in/raise_error_spec.rb index 07d3f5d09..bd43d7871 100644 --- a/spec/rspec/matchers/built_in/raise_error_spec.rb +++ b/spec/rspec/matchers/built_in/raise_error_spec.rb @@ -105,11 +105,35 @@ def to_s end it "fails if a different error instance is thrown from the one that is expected" do - s = StandardError.new("Error 1") + error = StandardError.new("Error 1") to_raise = StandardError.new("Error 2") expect do - expect { raise to_raise }.to raise_error(s) - end.to fail_with(Regexp.new("expected #{s.inspect}, got #{to_raise.inspect} with backtrace")) + expect { raise to_raise }.to raise_error(error) + end.to fail_with(Regexp.new("expected #{error.inspect}, got #{to_raise.inspect} with message:\n # Error 2\nand with backtrace:")) + end + + it "fails without a message if a different error instance is thrown from the one that is expected" do + error = StandardError.new("Error 1") + to_raise = StandardError.new + expect do + expect { raise to_raise }.to raise_error(error) + end.to fail_with(Regexp.new("expected #{error.inspect}, got #{to_raise.inspect} with backtrace:")) + end + + it "fails without a message if a generic runtime error is thrown instead of the one that is expected" do + error = RuntimeError.new("Error 1") + to_raise = RuntimeError + expect do + expect { raise }.to raise_error(error) + end.to fail_with(Regexp.new("expected #{error.inspect}, got #{to_raise.inspect} with backtrace:")) + end + + it "fails without a message if an error with an empty message is thrown instead of the one that is expected" do + error = StandardError.new("Error 1") + to_raise = RuntimeError.new("") + expect do + expect { raise to_raise }.to raise_error(error) + end.to fail_with(Regexp.new("expected #{error.inspect}, got #{to_raise.inspect} with backtrace:")) end it "passes if an error class is expected and an instance of that class is thrown" do @@ -242,6 +266,12 @@ def to_s end.to fail_with(/expected Exception with \"blah\", got #/) end + it "fails if RuntimeError error is raised without a matching message" do + expect do + expect { raise "blarg\nblarg\nblam" }.to raise_error(/blah/) + end.to fail_with(/expected \/blah\/, got #/) + end + it "fails if any other error is raised with the wrong message" do expect do expect { raise NameError.new('blarg') }.to raise_error('blah') @@ -283,6 +313,12 @@ def to_s end.to fail_with(/expected Exception with \"blah\", got #/) end + it "fails if RuntimeError error is raised without a matching message" do + expect do + expect { raise "blarg\nblarg" }.to raise_error.with_message(/blah/) + end.to fail_with(/expected Exception with message matching \/blah\/, got # with message:\n # blarg\n # blarg/) + end + it "fails if any other error is raised with the wrong message" do expect do expect { raise NameError.new('blarg') }.to raise_error.with_message('blah')