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,
  :@supports_block_expectations,
  :@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_falsey, #be_nil, #be_true, #be_truthy, #be_within, #change, clear_generated_description, configuration, const_missing, #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
26
27
28
29
30
# File 'lib/rspec/matchers/matcher.rb', line 17

def initialize(name, &declarations)
  @name         = name
  @declarations = declarations
  @actual       = nil
  @diffable     = false
  @supports_block_expectations = false
  @expected_exception, @rescued_exception = nil, nil
  @match_for_should_not_block = nil
  @messages = {}
  @define_block_executed = false
  @block_method_differentiator = nil
  @deprecated_methods = Set.new
  @matcher_execution_context = nil
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

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



279
280
281
282
283
284
285
# File 'lib/rspec/matchers/matcher.rb', line 279

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



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

def actual
  @actual
end

- (Object) rescued_exception (readonly)

Returns the value of attribute rescued_exception



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

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")


246
247
248
249
250
251
# File 'lib/rspec/matchers/matcher.rb', line 246

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


214
215
216
# File 'lib/rspec/matchers/matcher.rb', line 214

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.



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

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)


255
256
257
# File 'lib/rspec/matchers/matcher.rb', line 255

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)


266
267
268
269
270
271
# File 'lib/rspec/matchers/matcher.rb', line 266

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) expected



39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/rspec/matchers/matcher.rb', line 39

def expected
  if @expected.size == 1
    RSpec.warn_deprecation(
      "Custom matchers in 3.x will set expected to be a single value "+
      "(when provided as such) rather than an array. This may change "+
      "the behaviour of your matcher.\n"+
      "To continue to access this as an array use `expected_as_array`\n"+
      "Called from: #{ RSpec::CallerFilter.first_non_rspec_line }\n\n"
    )
  end
  @expected
end

- (Object) expected_as_array



52
53
54
# File 'lib/rspec/matchers/matcher.rb', line 52

def expected_as_array
  @expected
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



177
178
179
# File 'lib/rspec/matchers/matcher.rb', line 177

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



197
198
199
# File 'lib/rspec/matchers/matcher.rb', line 197

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.



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/rspec/matchers/matcher.rb', line 67

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 = {}
    @deprecated_methods = Set.new

    @block_method_differentiator = DifferentiateBlockMethodTypes.new(*@expected, &@declarations)
    making_declared_methods_public do
      instance_eval_with_args(*@expected, &@declarations)
    end

    @define_block_executed = true
    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)



129
130
131
# File 'lib/rspec/matchers/matcher.rb', line 129

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)



141
142
143
# File 'lib/rspec/matchers/matcher.rb', line 141

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")


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

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

- (Object) matcher_execution_context



61
62
63
64
# File 'lib/rspec/matchers/matcher.rb', line 61

def matcher_execution_context
  RSpec.deprecate("`matcher_execution_context` on custom matchers")
  @matcher_execution_context
end

- (Object) matcher_execution_context=(value)



56
57
58
59
# File 'lib/rspec/matchers/matcher.rb', line 56

def matcher_execution_context=(value)
  RSpec.deprecate("`matcher_execution_context=` on custom matchers")
  @matcher_execution_context = value
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)


88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/rspec/matchers/matcher.rb', line 88

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)


273
274
275
# File 'lib/rspec/matchers/matcher.rb', line 273

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

- (Object) singleton_class



370
371
372
# File 'lib/rspec/matchers/matcher.rb', line 370

def singleton_class
  class << self; self; end
end

- (Object) supports_block_expectations



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

def supports_block_expectations
  @supports_block_expectations = true
end

- (Boolean) supports_block_expectations?

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:

  • (Boolean)


260
261
262
# File 'lib/rspec/matchers/matcher.rb', line 260

def supports_block_expectations?
  @supports_block_expectations
end