Skip to content

Commit

Permalink
Present the actual error message from raise_error
Browse files Browse the repository at this point in the history
Display the actual error message of the raised error when a raise_error
asserton fails.  The failure message will now include the error message
on a separate line followed by the backtrace.  If there is no error
message, only the backtrace will be shown.
  • Loading branch information
genehsu committed Nov 3, 2021
1 parent dba6798 commit c1ddbf5
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 7 deletions.
27 changes: 23 additions & 4 deletions lib/rspec/matchers/built_in/raise_error.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand All @@ -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
Expand Down
42 changes: 39 additions & 3 deletions spec/rspec/matchers/built_in/raise_error_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -242,6 +266,12 @@ def to_s
end.to fail_with(/expected Exception with \"blah\", got #<RuntimeError: blarg>/)
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 #<RuntimeError: blarg\nblarg\nblam>/)
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')
Expand Down Expand Up @@ -283,6 +313,12 @@ def to_s
end.to fail_with(/expected Exception with \"blah\", got #<RuntimeError: blarg>/)
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 #<RuntimeError: blarg\nblarg> 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')
Expand Down

0 comments on commit c1ddbf5

Please sign in to comment.