123456789_123456789_123456789_123456789_123456789_

Class: RSpec::Matchers::BuiltIn::RaiseError Private

Do not use. This class is for internal use only.
Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Instance Chain:
Inherits: Object
Defined in: rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb

Overview

Provides the implementation for RSpec::Matchers#raise_error. Not intended to be instantiated directly.

rubocop:disable Lint/RescueException

Constant Summary

  • UndefinedValue =

    Used as a sentinel value to be able to tell when the user did not pass an argument. We can’t use nil for that because we need to warn when nil is passed in a different way. It’s an Object, not a Module, since Module’s === does not evaluate to true when compared to itself.

    Note; this is the default value supplied for expected_error_or_message, but because there are two method-calls involved, that default is actually supplied in the definition of the matcher method, ‘RSpec::Matchers#raise_error`

    # File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 20
    Object.new.freeze

Class Method Summary

Instance Attribute Summary

Instance Method Summary

::RSpec::Matchers::Composable - Included

#&

Alias for Composable#and.

#===

Delegates to #matches?.

#and

Creates a compound and expectation.

#description_of

Returns the description of the given object in a way that is aware of composed matchers.

#or

Creates a compound or expectation.

#values_match?

This provides a generic way to fuzzy-match an expected value against an actual value.

#|

Alias for Composable#or.

#should_enumerate?

We should enumerate arrays as long as they are not recursive.

#surface_descriptions_in

Transforms the given data structure (typically a hash or array) into a new data structure that, when #inspect is called on it, will provide descriptions of any contained matchers rather than the normal #inspect output.

#unreadable_io?,
#with_matchers_cloned

Historically, a single matcher instance was only checked against a single value.

Instance Attribute Details

#block_matches?Boolean (readonly, private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 137

def block_matches?
  @eval_block ? @eval_block_passed : true
end

#error_and_message_match?Boolean (readonly, private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 133

def error_and_message_match?
  @raised_expected_error && @with_expected_message
end

#expectation_matched?Boolean (readonly, private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 129

def expectation_matched?
  error_and_message_match? && block_matches?
end

#expecting_specific_exception?Boolean (readonly, private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 257

def expecting_specific_exception?
  @expected_error != Exception
end

#expects_call_stack_jump?Boolean (readonly)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 99

def expects_call_stack_jump?
  true
end

#ready_to_eval_block?Boolean (readonly, private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 141

def ready_to_eval_block?
  @raised_expected_error && @with_expected_message && @block
end

#supports_block_expectations?Boolean (readonly)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 89

def supports_block_expectations?
  true
end

#supports_value_expectations?Boolean (readonly)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 94

def supports_value_expectations?
  false
end

#warn_about_bare_error?Boolean (readonly, private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 180

def warn_about_bare_error?
  @warn_about_bare_error && @block.nil?
end

#warn_about_nil_error?Boolean (readonly, private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 184

def warn_about_nil_error?
  @warn_about_nil_error
end

Instance Method Details

#actual_error_message (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 123

def actual_error_message
  return nil unless @actual_error

  @actual_error.respond_to?(:original_message) ? @actual_error.original_message : @actual_error.message
end

#descriptionString

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 117

def description
  "raise #{expected_error}"
end

#does_not_match?(given_proc) ⇒ Boolean

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 83

def does_not_match?(given_proc)
  warn_for_negative_false_positives!
  !matches?(given_proc, :negative_expectation) && Proc === given_proc
end

#eval_block (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 145

def eval_block
  @eval_block = true
  begin
    @block[@actual_error]
    @eval_block_passed = true
  rescue Exception => err
    @actual_error = err
  end
end

#expected_error (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 226

def expected_error
  case @expected_message
  when nil
    if RSpec::Support.is_a_matcher?(@expected_error)
      "Exception with #{description_of(@expected_error)}"
    else
      description_of(@expected_error)
    end
  when Regexp
    "#{@expected_error} with message matching #{description_of(@expected_message)}"
  else
    "#{@expected_error} with #{description_of(@expected_message)}"
  end
end

#failure_messageString

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 105

def failure_message
  @eval_block ? actual_error_message : "expected #{expected_error}#{given_error}"
end

#failure_message_when_negatedString

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 111

def failure_message_when_negated
  "expected no #{expected_error}#{given_error}"
end

#format_backtrace(backtrace) (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 241

def format_backtrace(backtrace)
  formatter = Matchers.configuration.backtrace_formatter
  formatter.format_backtrace(backtrace)
end

#given_error (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 246

def given_error
  return " but was not given a block" unless Proc === @given_proc
  return " but nothing was raised" unless @actual_error

  backtrace = format_backtrace(@actual_error.backtrace)
  [
    ", got #{description_of(@actual_error)} with backtrace:",
    *backtrace
  ].join("\n  # ")
end

#handle_warning(message) (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 176

def handle_warning(message)
  RSpec::Expectations.configuration.false_positives_handler.call(message)
end

#matches?(given_proc, negative_expectation = false, &block) ⇒ Boolean

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 52

def matches?(given_proc, negative_expectation=false, &block)
  @given_proc = given_proc
  @block ||= block
  @raised_expected_error = false
  @with_expected_message = false
  @eval_block = false
  @eval_block_passed = false

  return false unless Proc === given_proc

  begin
    given_proc.call
  rescue Exception => @actual_error
    if values_match?(@expected_error, @actual_error) ||
       values_match?(@expected_error, actual_error_message)
      @raised_expected_error = true
      @with_expected_message = verify_message
    end
  end

  unless negative_expectation
    warn_about_bare_error! if warn_about_bare_error?
    warn_about_nil_error! if warn_about_nil_error?
    eval_block if ready_to_eval_block?
  end

  expectation_matched?
end

#raise_message_already_set (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 261

def raise_message_already_set
  raise "`expect { }.to raise_error(message).with_message(message)` is not valid. " \
        'The matcher only allows the expected message to be specified once'
end

#verify_message (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 155

def verify_message
  return true if @expected_message.nil?
  values_match?(@expected_message, actual_error_message.to_s)
end

#warn_about_bare_error! (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 188

def warn_about_bare_error!
  handle_warning("Using the `raise_error` matcher without providing a specific " \
                 "error or message risks false positives, since `raise_error` " \
                 "will match when Ruby raises a `NoMethodError`, `NameError` or " \
                 "`ArgumentError`, potentially allowing the expectation to pass " \
                 "without even executing the method you are intending to call. " \
                 "#{warning}"\
                 "Instead consider providing a specific error class or message. " \
                 "This message can be suppressed by setting: " \
                 "`RSpec::Expectations.configuration.on_potential_false" \
                 "_positives = :nothing`")
end

#warn_about_negative_false_positive!(expression) (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 214

def warn_about_negative_false_positive!(expression)
  handle_warning("Using #{expression} risks false positives, since literally " \
                 "any other error would cause the expectation to pass, " \
                 "including those raised by Ruby (e.g. `NoMethodError`, `NameError` " \
                 "and `ArgumentError`), meaning the code you are intending to test " \
                 "may not even get reached. Instead consider using " \
                 "`expect { }.not_to raise_error` or `expect { }.to raise_error" \
                 "(DifferentSpecificErrorClass)`. This message can be suppressed by " \
                 "setting: `RSpec::Expectations.configuration.on_potential_false" \
                 "_positives = :nothing`")
end

#warn_about_nil_error! (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 201

def warn_about_nil_error!
  handle_warning("Using the `raise_error` matcher with a `nil` error is probably " \
                 "unintentional, it risks false positives, since `raise_error` " \
                 "will match when Ruby raises a `NoMethodError`, `NameError` or " \
                 "`ArgumentError`, potentially allowing the expectation to pass " \
                 "without even executing the method you are intending to call. " \
                 "#{warning}"\
                 "Instead consider providing a specific error class or message. " \
                 "This message can be suppressed by setting: " \
                 "`RSpec::Expectations.configuration.on_potential_false" \
                 "_positives = :nothing`")
end

#warn_for_negative_false_positives! (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 160

def warn_for_negative_false_positives!
  expression = if expecting_specific_exception? && @expected_message
                 "`expect { }.not_to raise_error(SpecificErrorClass, message)`"
               elsif expecting_specific_exception?
                 "`expect { }.not_to raise_error(SpecificErrorClass)`"
               elsif @expected_message
                 "`expect { }.not_to raise_error(message)`"
               elsif @warn_about_nil_error
                 "`expect { }.not_to raise_error(nil)`"
               end

  return unless expression

  warn_about_negative_false_positive! expression
end

#warning (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 266

def warning
  warning = "Actual error raised was #{description_of(@actual_error)}. "
  warning if @actual_error
end

#with_message(expected_message)

Specifies the expected error message.

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb', line 43

def with_message(expected_message)
  raise_message_already_set if @expected_message
  @warn_about_bare_error = false
  @expected_message = expected_message
  self
end