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

PERSISTENT_INSTANCE_VARIABLES =
[
  :@name, :@declarations, :@diffable,
  :@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, is_a_matcher?, #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 Pretty

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

Methods included from Extensions::InstanceEvalWithArgs

#instance_eval_with_args

Constructor Details

- (Matcher) initialize(name)

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.

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

- (Object) method_missing(method, *args) (private)

232
233
234
235
236
237
238
# File 'lib/rspec/matchers/matcher.rb', line 232
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

- (Object) actual (readonly)

Returns the value of attribute actual

13
14
15
# File 'lib/rspec/matchers/matcher.rb', line 13
def actual
  @actual
end

- (Object) expected (readonly)

Returns the value of attribute expected

13
14
15
# File 'lib/rspec/matchers/matcher.rb', line 13
def expected
  @expected
end

- (Object) matcher_execution_context

Returns the value of attribute matcherexecutioncontext

14
15
16
# File 'lib/rspec/matchers/matcher.rb', line 14
def matcher_execution_context
  @matcher_execution_context
end

- (Object) rescued_exception (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

- (Object) chain(method)

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")
204
205
206
207
208
209
# File 'lib/rspec/matchers/matcher.rb', line 204
def chain(method, &block)
  define_method method do |*args|
    block.call(*args)
    self
  end
end

- (Object) description

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
176
177
178
# File 'lib/rspec/matchers/matcher.rb', line 176
def description(&block)
  cache_or_call_cached(:description, &block)
end

- (Object) diffable

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

182
183
184
# File 'lib/rspec/matchers/matcher.rb', line 182
def diffable
  @diffable = true
end

- (Boolean) diffable?

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)
213
214
215
# File 'lib/rspec/matchers/matcher.rb', line 213
def diffable?
  @diffable
end

- (Boolean) does_not_match?(actual)

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)
219
220
221
222
223
224
# File 'lib/rspec/matchers/matcher.rb', line 219
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

- (Object) failure_message_for_should {|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

139
140
141
# File 'lib/rspec/matchers/matcher.rb', line 139
def failure_message_for_should(&block)
  cache_or_call_cached(:failure_message_for_should, &block)
end

- (Object) failure_message_for_should_not {|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

159
160
161
# File 'lib/rspec/matchers/matcher.rb', line 159
def failure_message_for_should_not(&block)
  cache_or_call_cached(:failure_message_for_should_not, &block)
end

- (Object) for_expected(*expected)

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
46
# 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
    @messages = {}
    making_declared_methods_public do
      instance_eval_with_args(*@expected, &@declarations)
    end
    self
  end
end

- (Object) match {|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)

91
92
93
# File 'lib/rspec/matchers/matcher.rb', line 91
def match(&block)
  @match_block = block
end

- (Object) match_for_should_not {|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)

103
104
105
# File 'lib/rspec/matchers/matcher.rb', line 103
def match_for_should_not(&block)
  @match_for_should_not_block = block
end

- (Object) match_unless_raises(exception = Exception)

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("person@company.com")
119
120
121
122
# File 'lib/rspec/matchers/matcher.rb', line 119
def match_unless_raises(exception=Exception, &block)
  @expected_exception = exception
  match(&block)
end

- (Boolean) matches?(actual)

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)
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/rspec/matchers/matcher.rb', line 50
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

- (Boolean) respond_to?(method, include_private = false)

Returns:

  • (Boolean)
226
227
228
# File 'lib/rspec/matchers/matcher.rb', line 226
def respond_to?(method, include_private=false)
  super || matcher_execution_context.respond_to?(method, include_private)
end

- (Object) singleton_class

293
294
295
# File 'lib/rspec/matchers/matcher.rb', line 293
def singleton_class
  class << self; self; end
end