Class: RSpec::Matchers::DSL::Matcher

Inherits:
Object
  • Object
show all
Includes:
RSpec::Matchers, Extensions::InstanceEvalWithArgs, Pretty
Defined in:
lib/rspec/matchers/matcher.rb

Overview

Provides the context in which the block passed to RSpec::Matchers.define will be evaluated.

Constant Summary collapse

PERSISTENT_INSTANCE_VARIABLES =
[
  :@name, :@declarations, :@diffable, :@messages,
  :@match_block, :@match_for_should_not_block,
  :@expected_exception
].to_set

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from RSpec::Matchers

#be, #be_a, #be_a_kind_of, #be_an_instance_of, #be_close, #be_false, #be_nil, #be_true, #be_within, #change, clear_generated_description, configuration, #cover, #end_with, #eq, #eql, #equal, #exist, generated_description, #have, #have_at_least, #have_at_most, #match_array, #raise_error, #respond_to, #satisfy, #start_with, #throw_symbol, #yield_control, #yield_successive_args, #yield_with_args, #yield_with_no_args

Methods included from RSpec::Matchers::DSL

#define

Methods included from Pretty

#_pretty_print, #expected_to_sentence, #name, #name_to_sentence, #split_words, #to_sentence, #underscore

Methods included from Extensions::InstanceEvalWithArgs

#instance_eval_with_args

Constructor Details

#initialize(name, &declarations) ⇒ Matcher

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of Matcher.



17
18
19
20
21
22
23
24
25
# File 'lib/rspec/matchers/matcher.rb', line 17

def initialize(name, &declarations)
  @name         = name
  @declarations = declarations
  @actual       = nil
  @diffable     = false
  @expected_exception, @rescued_exception = nil, nil
  @match_for_should_not_block = nil
  @messages = {}
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object (private)



231
232
233
234
235
236
237
# File 'lib/rspec/matchers/matcher.rb', line 231

def method_missing(method, *args, &block)
  if matcher_execution_context.respond_to?(method)
    matcher_execution_context.send method, *args, &block
  else
    super(method, *args, &block)
  end
end

Instance Attribute Details

#actualObject (readonly)

Returns the value of attribute actual.



13
14
15
# File 'lib/rspec/matchers/matcher.rb', line 13

def actual
  @actual
end

#expectedObject (readonly)

Returns the value of attribute expected.



13
14
15
# File 'lib/rspec/matchers/matcher.rb', line 13

def expected
  @expected
end

#matcher_execution_contextObject

Returns the value of attribute matcher_execution_context.



14
15
16
# File 'lib/rspec/matchers/matcher.rb', line 14

def matcher_execution_context
  @matcher_execution_context
end

#rescued_exceptionObject (readonly)

Returns the value of attribute rescued_exception.



13
14
15
# File 'lib/rspec/matchers/matcher.rb', line 13

def rescued_exception
  @rescued_exception
end

Instance Method Details

#chain(method, &block) ⇒ Object

Convenience for defining methods on this matcher to create a fluent interface. The trick about fluent interfaces is that each method must return self in order to chain methods together. chain handles that for you.

Examples:


RSpec::Matchers.define :have_errors_on do |key|
  chain :with do |message|
    @message = message
  end

  match do |actual|
    actual.errors[key] == @message
  end
end

minor.should have_errors_on(:age).with("Not old enough to participate")


203
204
205
206
207
208
# File 'lib/rspec/matchers/matcher.rb', line 203

def chain(method, &block)
  define_method method do |*args|
    block.call(*args)
    self
  end
end

#description(&block) ⇒ Object

Customize the description to use for one-liners. Only use this when the description generated by default doesn't suit your needs.

Examples:


RSpec::Matchers.define :qualify_for do |expected|
  match { ... }

  description do
    "qualify for #{expected}"
  end
end


175
176
177
# File 'lib/rspec/matchers/matcher.rb', line 175

def description(&block)
  cache_or_call_cached(:description, &block)
end

#diffableObject

Tells the matcher to diff the actual and expected values in the failure message.



181
182
183
# File 'lib/rspec/matchers/matcher.rb', line 181

def diffable
  @diffable = true
end

#diffable?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Used internally by objects returns by +should+ and +should_not+.

Returns:

  • (Boolean)


212
213
214
# File 'lib/rspec/matchers/matcher.rb', line 212

def diffable?
  @diffable
end

#does_not_match?(actual) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Used internally by +should_not+

Returns:

  • (Boolean)


218
219
220
221
222
223
# File 'lib/rspec/matchers/matcher.rb', line 218

def does_not_match?(actual)
  @actual = actual
  @match_for_should_not_block ?
    instance_eval_with_args(actual, &@match_for_should_not_block) :
    !matches?(actual)
end

#failure_message_for_should {|Object| ... } ⇒ Object

Customize the failure messsage to use when this matcher is invoked with should. Only use this when the message generated by default doesn't suit your needs.

Examples:


RSpec::Matchers.define :have_strength do |expected|
  match { ... }

  failure_message_for_should do |actual|
    "Expected strength of #{expected}, but had #{actual.strength}"
  end
end

Yields:

  • (Object)

    actual the actual object



138
139
140
# File 'lib/rspec/matchers/matcher.rb', line 138

def failure_message_for_should(&block)
  cache_or_call_cached(:failure_message_for_should, &block)
end

#failure_message_for_should_not {|Object| ... } ⇒ Object

Customize the failure messsage to use when this matcher is invoked with should_not. Only use this when the message generated by default doesn't suit your needs.

Examples:


RSpec::Matchers.define :have_strength do |expected|
  match { ... }

  failure_message_for_should_not do |actual|
    "Expected not to have strength of #{expected}, but did"
  end
end

Yields:

  • (Object)

    actual the actual object

  • (Object)

    actual the actual object



158
159
160
# File 'lib/rspec/matchers/matcher.rb', line 158

def failure_message_for_should_not(&block)
  cache_or_call_cached(:failure_message_for_should_not, &block)
end

#for_expected(*expected) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/rspec/matchers/matcher.rb', line 34

def for_expected(*expected)
  @expected = expected
  dup.instance_eval do
    instance_variables.map {|ivar| ivar.intern}.each do |ivar|
      instance_variable_set(ivar, nil) unless (PERSISTENT_INSTANCE_VARIABLES + [:@expected]).include?(ivar)
    end
    making_declared_methods_public do
      instance_eval_with_args(*@expected, &@declarations)
    end
    self
  end
end

#match {|Object| ... } ⇒ Object Also known as: match_for_should

Stores the block that is used to determine whether this matcher passes or fails. The block should return a boolean value. When the matcher is passed to should and the block returns true, then the expectation passes. Similarly, when the matcher is passed to should_not and the block returns false, then the expectation passes.

Use match_for_should when used in conjuntion with match_for_should_not.

Examples:


RSpec::Matchers.define :be_even do
  match do |actual|
    actual.even?
  end
end

4.should be_even     # passes
3.should_not be_even # passes
3.should be_even     # fails
4.should_not be_even # fails

Yields:

  • (Object)

    actual the actual value (or receiver of should)



90
91
92
# File 'lib/rspec/matchers/matcher.rb', line 90

def match(&block)
  @match_block = block
end

#match_for_should_not {|Object| ... } ⇒ Object

Use this to define the block for a negative expectation (should_not) when the positive and negative forms require different handling. This is rarely necessary, but can be helpful, for example, when specifying asynchronous processes that require different timeouts.

Yields:

  • (Object)

    actual the actual value (or receiver of should)



102
103
104
# File 'lib/rspec/matchers/matcher.rb', line 102

def match_for_should_not(&block)
  @match_for_should_not_block = block
end

#match_unless_raises(exception = Exception, &block) ⇒ Object

Use this instead of match when the block will raise an exception rather than returning false to indicate a failure.

Examples:


RSpec::Matchers.define :accept_as_valid do |candidate_address|
  match_unless_raises ValidationException do |validator|
    validator.validate(candidate_address)
  end
end

email_validator.should accept_as_valid("[email protected]")


118
119
120
121
# File 'lib/rspec/matchers/matcher.rb', line 118

def match_unless_raises(exception=Exception, &block)
  @expected_exception = exception
  match(&block)
end

#matches?(actual) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Used internally by +should+ and +should_not+.

Returns:

  • (Boolean)


49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/rspec/matchers/matcher.rb', line 49

def matches?(actual)
  @actual = actual
  if @expected_exception
    begin
      instance_eval_with_args(actual, &@match_block)
      true
    rescue @expected_exception => @rescued_exception
      false
    end
  else
    begin
      instance_eval_with_args(actual, &@match_block)
    rescue RSpec::Expectations::ExpectationNotMetError
      false
    end
  end
end

#respond_to?(method, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


225
226
227
# File 'lib/rspec/matchers/matcher.rb', line 225

def respond_to?(method, include_private=false)
  super || matcher_execution_context.respond_to?(method, include_private)
end