Permalink
Browse files

Don't silence 2nd exceptions.

When an example raises an error and an after or around hook also raises an error, the 2nd error was being silenced, since `set_exception` was a no-op when the exception was already set.  Silencing errors is bad, so we should print the error instead.

See https://github.com/myronmarston/vcr/issues/167#issuecomment-5814249 for the issue that triggered this change.
  • Loading branch information...
1 parent 3c1ed24 commit 27059bf1fd39589af3e042485ba366fc06b4ecbe @myronmarston myronmarston committed May 22, 2012
Showing with 43 additions and 2 deletions.
  1. +19 −2 lib/rspec/core/example.rb
  2. +24 −0 spec/rspec/core/example_spec.rb
View
21 lib/rspec/core/example.rb
@@ -131,7 +131,7 @@ def run(example_group_instance, reporter)
begin
assign_auto_description
rescue Exception => e
- set_exception(e)
+ set_exception(e, "while assigning the example description")
end
end
@@ -204,7 +204,20 @@ def around_each_hooks
#
# Used internally to set an exception in an after hook, which
# captures the exception but doesn't raise it.
- def set_exception(exception)
+ def set_exception(exception, context=nil)
+ if @exception
+ # An error has already been set; we don't want to override it,
+ # but we also don't want silence the error, so let's print it.
+ msg = <<-EOS
+
+An error occurred #{context}
+ #{exception.class}: #{exception.message}
+ occurred at #{exception.backtrace.first}
+
+ EOS
+ RSpec.configuration.reporter.message(msg)
+ end
+
@exception ||= exception
end
@@ -241,6 +254,8 @@ def with_around_each_hooks(&block)
else
@example_group_class.run_around_each_hooks(self, Example.procsy(metadata, &block))
end
+ rescue Exception => e
+ set_exception(e, "in an around(:each) hook")
end
def start(reporter)
@@ -287,6 +302,8 @@ def run_before_each
def run_after_each
@example_group_class.run_after_each_hooks(self)
@example_group_instance.verify_mocks_for_rspec if @example_group_instance.respond_to?(:verify_mocks_for_rspec)
+ rescue Exception => e
+ set_exception(e, "in an after(:each) hook")
ensure
@example_group_instance.teardown_mocks_for_rspec if @example_group_instance.respond_to?(:teardown_mocks_for_rspec)
end
View
24 spec/rspec/core/example_spec.rb
@@ -258,6 +258,30 @@ def assert(val)
group.run.should be_true
end
end
+
+ context "when the example and an around hook raise errors" do
+ it "prints the around hook error rather than silencing it" do
+ group = RSpec::Core::ExampleGroup.describe do
+ around(:each) { |e| e.run; raise "around" }
+ example("e") { raise "example" }
+ end
+
+ RSpec.configuration.reporter.should_receive(:message).with(/An error occurred/)
+ group.run
+ end
+ end
+
+ context "when the example and an after hook raise errors" do
+ it "prints the after hook error rather than silencing it" do
+ group = RSpec::Core::ExampleGroup.describe do
+ after(:each) { raise "after" }
+ example("e") { raise "example" }
+ end
+
+ RSpec.configuration.reporter.should_receive(:message).with(/An error occurred.*after/)
+ group.run
+ end
+ end
end
describe "#pending" do

0 comments on commit 27059bf

Please sign in to comment.