Skip to content

Instantly share code, notes, and snippets.

@chendo
Created December 20, 2011 04:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chendo/1500276 to your computer and use it in GitHub Desktop.
Save chendo/1500276 to your computer and use it in GitHub Desktop.
A matcher based on RaiseException that also prints the backtrace of the original exception
# Copied from the rspec 1.3.2 RaiseException matcher
# Behaves exactly the same, except it also prints the backtrace of the original exception
module Spec
module Matchers
class ThrowException #:nodoc:
def initialize(expected_exception_or_message=Exception, expected_message=nil, &block)
@block = block
@actual_exception = nil
case expected_exception_or_message
when String, Regexp
@expected_exception, @expected_message = Exception, expected_exception_or_message
else
@expected_exception, @expected_message = expected_exception_or_message, expected_message
end
end
def matches?(given_proc)
@raised_expected_exception = false
@with_expected_message = false
@eval_block = false
@eval_block_passed = false
begin
given_proc.call
rescue @expected_exception => @actual_exception
@raised_expected_exception = true
@with_expected_message = verify_message
rescue Exception => @actual_exception
# This clause should be empty, but rcov will not report it as covered
# unless something (anything) is executed within the clause
rcov_exception_report = "http://eigenclass.org/hiki.rb?rcov-0.8.0"
end
unless negative_expectation?
eval_block if @raised_expected_exception && @with_expected_message && @block
end
(@raised_expected_exception & @with_expected_message) ? (@eval_block ? @eval_block_passed : true) : false
end
def eval_block
@eval_block = true
begin
@block[@actual_exception]
@eval_block_passed = true
rescue Exception => err
@actual_exception = err
end
end
def verify_message
case @expected_message
when nil
true
when Regexp
@expected_message =~ @actual_exception.message
else
@expected_message == @actual_exception.message
end
end
def failure_message_for_should
@eval_block ? @actual_exception.message : "expected #{expected_exception}#{given_exception}"
end
def failure_message_for_should_not
"expected no #{expected_exception}#{given_exception}"
end
def description
"raise #{expected_exception}"
end
private
def expected_exception
case @expected_message
when nil
@expected_exception
when Regexp
"#{@expected_exception} with message matching #{@expected_message.inspect}"
else
"#{@expected_exception} with #{@expected_message.inspect}"
end
end
def given_exception
@actual_exception.nil? ? " but nothing was raised" : ", got #{@actual_exception.inspect}\nOriginal backtrace:\n#{original_backtrace}\n\n"
end
def original_backtrace
@actual_exception.backtrace.join("\n")
end
def negative_expectation?
# YES - I'm a bad person... help me find a better way - ryand
caller.first(3).find { |s| s =~ /should_not/ }
end
end
def throw_exception(exception=Exception, message=nil, &block)
Matchers::ThrowException.new(exception, message, &block)
end
alias_method :throw_error, :throw_exception
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment