rspec-mocks 2.13.1 → 2.14.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. data/Changelog.md +45 -4
  2. data/README.md +1 -1
  3. data/features/argument_matchers/README.md +2 -2
  4. data/features/argument_matchers/explicit.feature +2 -3
  5. data/features/argument_matchers/general_matchers.feature +2 -2
  6. data/features/argument_matchers/type_matchers.feature +3 -4
  7. data/features/message_expectations/README.md +2 -2
  8. data/features/message_expectations/any_instance.feature +2 -2
  9. data/features/message_expectations/block_local_expectations.feature.pending +3 -3
  10. data/features/message_expectations/expect_message_using_expect.feature +103 -0
  11. data/features/message_expectations/expect_message_using_should_receive.feature +118 -0
  12. data/features/message_expectations/receive_counts.feature +1 -1
  13. data/features/method_stubs/README.md +1 -1
  14. data/features/method_stubs/any_instance.feature +11 -11
  15. data/features/method_stubs/as_null_object.feature +1 -1
  16. data/features/method_stubs/stub_implementation.feature +2 -2
  17. data/features/outside_rspec/configuration.feature +0 -20
  18. data/features/spies/spy_partial_mock_method.feature +34 -0
  19. data/features/spies/spy_pure_mock_method.feature +76 -0
  20. data/features/spies/spy_unstubbed_method.feature +18 -0
  21. data/features/step_definitions/additional_cli_steps.rb +7 -0
  22. data/features/test_frameworks/test_unit.feature +43 -0
  23. data/lib/rspec/mocks.rb +9 -34
  24. data/lib/rspec/mocks/any_instance/chain.rb +8 -2
  25. data/lib/rspec/mocks/any_instance/expectation_chain.rb +19 -16
  26. data/lib/rspec/mocks/any_instance/recorder.rb +6 -3
  27. data/lib/rspec/mocks/any_instance/stub_chain.rb +11 -11
  28. data/lib/rspec/mocks/any_instance/stub_chain_chain.rb +8 -10
  29. data/lib/rspec/mocks/argument_list_matcher.rb +7 -3
  30. data/lib/rspec/mocks/configuration.rb +28 -1
  31. data/lib/rspec/mocks/deprecation.rb +18 -0
  32. data/lib/rspec/mocks/error_generator.rb +60 -8
  33. data/lib/rspec/mocks/errors.rb +1 -1
  34. data/lib/rspec/mocks/example_methods.rb +39 -3
  35. data/lib/rspec/mocks/extensions/marshal.rb +4 -10
  36. data/lib/rspec/mocks/framework.rb +16 -4
  37. data/lib/rspec/mocks/instance_method_stasher.rb +3 -0
  38. data/lib/rspec/mocks/matchers/have_received.rb +93 -0
  39. data/lib/rspec/mocks/matchers/receive.rb +92 -0
  40. data/lib/rspec/mocks/message_expectation.rb +66 -129
  41. data/lib/rspec/mocks/method_double.rb +50 -43
  42. data/lib/rspec/mocks/mutate_const.rb +8 -20
  43. data/lib/rspec/mocks/proxy.rb +41 -25
  44. data/lib/rspec/mocks/proxy_for_nil.rb +36 -0
  45. data/lib/rspec/mocks/space.rb +64 -11
  46. data/lib/rspec/mocks/stub_chain.rb +51 -0
  47. data/lib/rspec/mocks/syntax.rb +329 -0
  48. data/lib/rspec/mocks/targets.rb +69 -0
  49. data/lib/rspec/mocks/test_double.rb +25 -4
  50. data/lib/rspec/mocks/version.rb +1 -1
  51. data/lib/spec/mocks.rb +1 -3
  52. data/spec/rspec/mocks/and_call_original_spec.rb +8 -0
  53. data/spec/rspec/mocks/and_yield_spec.rb +6 -6
  54. data/spec/rspec/mocks/any_instance_spec.rb +43 -31
  55. data/spec/rspec/mocks/any_number_of_times_spec.rb +6 -0
  56. data/spec/rspec/mocks/argument_expectation_spec.rb +12 -14
  57. data/spec/rspec/mocks/at_least_spec.rb +46 -37
  58. data/spec/rspec/mocks/at_most_spec.rb +12 -12
  59. data/spec/rspec/mocks/block_return_value_spec.rb +18 -1
  60. data/spec/rspec/mocks/bug_report_10260_spec.rb +1 -1
  61. data/spec/rspec/mocks/bug_report_10263_spec.rb +1 -1
  62. data/spec/rspec/mocks/bug_report_11545_spec.rb +4 -4
  63. data/spec/rspec/mocks/bug_report_600_spec.rb +1 -1
  64. data/spec/rspec/mocks/bug_report_7611_spec.rb +1 -1
  65. data/spec/rspec/mocks/configuration_spec.rb +124 -0
  66. data/spec/rspec/mocks/double_spec.rb +13 -1
  67. data/spec/rspec/mocks/failing_argument_matchers_spec.rb +17 -1
  68. data/spec/rspec/mocks/hash_excluding_matcher_spec.rb +13 -13
  69. data/spec/rspec/mocks/matchers/have_received_spec.rb +266 -0
  70. data/spec/rspec/mocks/matchers/receive_spec.rb +318 -0
  71. data/spec/rspec/mocks/methods_spec.rb +27 -0
  72. data/spec/rspec/mocks/mock_ordering_spec.rb +4 -4
  73. data/spec/rspec/mocks/mock_space_spec.rb +94 -39
  74. data/spec/rspec/mocks/mock_spec.rb +65 -50
  75. data/spec/rspec/mocks/multiple_return_value_spec.rb +10 -10
  76. data/spec/rspec/mocks/mutate_const_spec.rb +21 -1
  77. data/spec/rspec/mocks/nil_expectation_warning_spec.rb +10 -4
  78. data/spec/rspec/mocks/null_object_mock_spec.rb +11 -2
  79. data/spec/rspec/mocks/once_counts_spec.rb +5 -5
  80. data/spec/rspec/mocks/options_hash_spec.rb +4 -4
  81. data/spec/rspec/mocks/partial_mock_spec.rb +20 -11
  82. data/spec/rspec/mocks/partial_mock_using_mocks_directly_spec.rb +7 -7
  83. data/spec/rspec/mocks/passing_argument_matchers_spec.rb +2 -2
  84. data/spec/rspec/mocks/precise_counts_spec.rb +6 -6
  85. data/spec/rspec/mocks/serialization_spec.rb +1 -22
  86. data/spec/rspec/mocks/stash_spec.rb +4 -12
  87. data/spec/rspec/mocks/stub_implementation_spec.rb +3 -3
  88. data/spec/rspec/mocks/stub_spec.rb +44 -20
  89. data/spec/rspec/mocks/stubbed_message_expectations_spec.rb +6 -6
  90. data/spec/rspec/mocks/twice_counts_spec.rb +6 -6
  91. data/spec/rspec/mocks_spec.rb +1 -3
  92. data/spec/spec_helper.rb +25 -1
  93. metadata +86 -81
  94. data/features/message_expectations/expect_message.feature +0 -94
  95. data/lib/rspec/mocks/any_instance.rb +0 -81
  96. data/lib/rspec/mocks/extensions/psych.rb +0 -23
  97. data/lib/rspec/mocks/methods.rb +0 -155
  98. data/lib/rspec/mocks/serialization.rb +0 -34
  99. data/spec/rspec/mocks/combining_implementation_instructions_spec.rb +0 -197
@@ -4,11 +4,6 @@ module RSpec
4
4
  # @private
5
5
  class StubChain < Chain
6
6
 
7
- # @private
8
- def initialize(*args, &block)
9
- record(:stub, *args, &block)
10
- end
11
-
12
7
  # @private
13
8
  def expectation_fulfilled?
14
9
  true
@@ -16,13 +11,18 @@ module RSpec
16
11
 
17
12
  private
18
13
 
14
+ def create_message_expectation_on(instance)
15
+ proxy = ::RSpec::Mocks.proxy_for(instance)
16
+ expected_from = IGNORED_BACKTRACE_LINE
17
+ proxy.add_stub(expected_from, *@expectation_args, &@expectation_block)
18
+ end
19
+
19
20
  def invocation_order
20
21
  @invocation_order ||= {
21
- :stub => [nil],
22
- :with => [:stub],
23
- :and_return => [:with, :stub],
24
- :and_raise => [:with, :stub],
25
- :and_yield => [:with, :stub]
22
+ :with => [nil],
23
+ :and_return => [:with, nil],
24
+ :and_raise => [:with, nil],
25
+ :and_yield => [:with, nil]
26
26
  }
27
27
  end
28
28
 
@@ -34,4 +34,4 @@ module RSpec
34
34
  end
35
35
  end
36
36
  end
37
- end
37
+ end
@@ -4,22 +4,20 @@ module RSpec
4
4
  # @private
5
5
  class StubChainChain < StubChain
6
6
 
7
- # @private
8
- def initialize(*args, &block)
9
- record(:stub_chain, *args, &block)
10
- end
11
-
12
7
  private
13
8
 
9
+ def create_message_expectation_on(instance)
10
+ ::RSpec::Mocks::StubChain.stub_chain_on(instance, *@expectation_args, &@expectation_block)
11
+ end
12
+
14
13
  def invocation_order
15
14
  @invocation_order ||= {
16
- :stub_chain => [nil],
17
- :and_return => [:stub_chain],
18
- :and_raise => [:stub_chain],
19
- :and_yield => [:stub_chain]
15
+ :and_return => [nil],
16
+ :and_raise => [nil],
17
+ :and_yield => [nil]
20
18
  }
21
19
  end
22
20
  end
23
21
  end
24
22
  end
25
- end
23
+ end
@@ -30,7 +30,7 @@ module RSpec
30
30
 
31
31
  # @api public
32
32
  # @param [Array] *expected_args a list of expected literals and/or argument matchers
33
- # @param [Block] block a block with arity matching the expected
33
+ # @param [Block] block a block with arity matching the expected
34
34
  #
35
35
  # Initializes an `ArgumentListMatcher` with a collection of literal
36
36
  # values and/or argument matchers, or a block that handles the evaluation
@@ -73,8 +73,12 @@ module RSpec
73
73
  return ArgumentMatchers::EqualityProxy.new(arg)
74
74
  end
75
75
 
76
- def is_matcher?(obj)
77
- !obj.null_object? & obj.respond_to?(:matches?) & [:failure_message_for_should, :failure_message].any? { |m| obj.respond_to?(m) }
76
+ def is_matcher?(object)
77
+ return false if object.respond_to?(:i_respond_to_everything_so_im_not_really_a_matcher)
78
+
79
+ [:failure_message_for_should, :failure_message].any? do |msg|
80
+ object.respond_to?(msg)
81
+ end && object.respond_to?(:matches?)
78
82
  end
79
83
 
80
84
  def block_passes?(*args)
@@ -19,10 +19,37 @@ module RSpec
19
19
  #
20
20
  def add_stub_and_should_receive_to(*modules)
21
21
  modules.each do |mod|
22
- mod.__send__(:include, RSpec::Mocks::Methods)
22
+ Syntax.enable_should(mod)
23
23
  end
24
24
  end
25
+
26
+ def syntax=(values)
27
+ if Array(values).include?(:expect)
28
+ Syntax.enable_expect
29
+ else
30
+ Syntax.disable_expect
31
+ end
32
+
33
+ if Array(values).include?(:should)
34
+ Syntax.enable_should
35
+ else
36
+ Syntax.disable_should
37
+ end
38
+ end
39
+
40
+ def syntax
41
+ syntaxes = []
42
+ syntaxes << :should if Syntax.should_enabled?
43
+ syntaxes << :expect if Syntax.expect_enabled?
44
+ syntaxes
45
+ end
25
46
  end
47
+
48
+ def self.configuration
49
+ @configuration ||= Configuration.new
50
+ end
51
+
52
+ configuration.syntax = [:should, :expect]
26
53
  end
27
54
  end
28
55
 
@@ -0,0 +1,18 @@
1
+ module RSpec
2
+ module Mocks
3
+ module Deprecation
4
+ # @private
5
+ #
6
+ # Used internally to print deprecation warnings
7
+ def deprecate(deprecated, options={})
8
+ message = "DEPRECATION: #{deprecated} is deprecated."
9
+ message << " Use #{options[:replacement]} instead." if options[:replacement]
10
+ message << " Called from #{caller(0)[2]}."
11
+ warn message
12
+ end
13
+ end
14
+ end
15
+
16
+ extend(Mocks::Deprecation) unless respond_to?(:deprecate)
17
+ end
18
+
@@ -23,27 +23,59 @@ module RSpec
23
23
  # @private
24
24
  def raise_unexpected_message_args_error(expectation, *args)
25
25
  expected_args = format_args(*expectation.expected_args)
26
- actual_args = format_args(*args)
26
+ actual_args = format_received_args(*args)
27
27
  __raise "#{intro} received #{expectation.message.inspect} with unexpected arguments\n expected: #{expected_args}\n got: #{actual_args}"
28
28
  end
29
29
 
30
30
  # @private
31
31
  def raise_missing_default_stub_error(expectation, *args)
32
32
  expected_args = format_args(*expectation.expected_args)
33
- actual_args = format_args(*args)
33
+ actual_args = format_received_args(*args)
34
34
  __raise "#{intro} received #{expectation.message.inspect} with unexpected arguments\n expected: #{expected_args}\n got: #{actual_args}\n Please stub a default value first if message might be received with other args as well. \n"
35
35
  end
36
36
 
37
37
  # @private
38
38
  def raise_similar_message_args_error(expectation, *args_for_multiple_calls)
39
39
  expected_args = format_args(*expectation.expected_args)
40
- actual_args = args_for_multiple_calls.collect {|a| format_args(*a)}.join(", ")
40
+ actual_args = args_for_multiple_calls.collect {|a| format_received_args(*a)}.join(", ")
41
41
  __raise "#{intro} received #{expectation.message.inspect} with unexpected arguments\n expected: #{expected_args}\n got: #{actual_args}"
42
42
  end
43
43
 
44
44
  # @private
45
- def raise_expectation_error(message, expected_received_count, actual_received_count, *args)
46
- __raise "(#{intro}).#{message}#{format_args(*args)}\n expected: #{count_message(expected_received_count)}\n received: #{count_message(actual_received_count)}"
45
+ def raise_expectation_error(message, expected_received_count, argument_list_matcher, actual_received_count, expectation_count_type, *args)
46
+ expected_part = expected_part_of_expectation_error(expected_received_count, expectation_count_type, argument_list_matcher)
47
+ received_part = received_part_of_expectation_error(actual_received_count, *args)
48
+ __raise "(#{intro}).#{message}#{format_args(*args)}\n #{expected_part}\n #{received_part}"
49
+ end
50
+
51
+ # @private
52
+ def received_part_of_expectation_error(actual_received_count, *args)
53
+ "received: #{count_message(actual_received_count)}" +
54
+ method_call_args_description(args)
55
+ end
56
+
57
+ # @private
58
+ def expected_part_of_expectation_error(expected_received_count, expectation_count_type, argument_list_matcher)
59
+ "expected: #{count_message(expected_received_count, expectation_count_type)}" +
60
+ method_call_args_description(argument_list_matcher.expected_args)
61
+ end
62
+
63
+ # @private
64
+ def method_call_args_description(args)
65
+ if args.first.is_a?(ArgumentMatchers::AnyArgsMatcher)
66
+ " with any arguments"
67
+ elsif args.first.is_a?(ArgumentMatchers::NoArgsMatcher)
68
+ " with no arguments"
69
+ elsif args.length > 0
70
+ " with arguments: #{args.inspect.gsub(/\A\[(.+)\]\z/, '(\1)')}"
71
+ else
72
+ ""
73
+ end
74
+ end
75
+
76
+ # @private
77
+ def describe_expectation(message, expected_received_count, actual_received_count, *args)
78
+ "have received #{message}#{format_args(*args)} #{count_message(expected_received_count)}"
47
79
  end
48
80
 
49
81
  # @private
@@ -72,6 +104,18 @@ module RSpec
72
104
  "available on a partial mock object."
73
105
  end
74
106
 
107
+ # @private
108
+ def raise_expectation_on_unstubbed_method(method)
109
+ __raise "#{intro} expected to have received #{method}, but that " +
110
+ "method has not been stubbed."
111
+ end
112
+
113
+ # @private
114
+ def raise_expectation_on_mocked_method(method)
115
+ __raise "#{intro} expected to have received #{method}, but that " +
116
+ "method has been mocked instead of stubbed."
117
+ end
118
+
75
119
  private
76
120
 
77
121
  def intro
@@ -105,8 +149,17 @@ module RSpec
105
149
  args.collect {|arg| arg.respond_to?(:description) ? arg.description : arg.inspect}.join(", ")
106
150
  end
107
151
 
108
- def count_message(count)
109
- return "at least #{pretty_print(count.abs)}" if count < 0
152
+ def format_received_args(*args)
153
+ args.empty? ? "(no args)" : "(" + received_arg_list(*args) + ")"
154
+ end
155
+
156
+ def received_arg_list(*args)
157
+ args.collect(&:inspect).join(", ")
158
+ end
159
+
160
+ def count_message(count, expectation_count_type=nil)
161
+ return "at least #{pretty_print(count.abs)}" if count < 0 || expectation_count_type == :at_least
162
+ return "at most #{pretty_print(count)}" if expectation_count_type == :at_most
110
163
  return pretty_print(count)
111
164
  end
112
165
 
@@ -117,4 +170,3 @@ module RSpec
117
170
  end
118
171
  end
119
172
  end
120
-
@@ -3,7 +3,7 @@ module RSpec
3
3
  # @private
4
4
  class MockExpectationError < Exception
5
5
  end
6
-
6
+
7
7
  # @private
8
8
  class AmbiguousReturnError < StandardError
9
9
  end
@@ -31,13 +31,15 @@ module RSpec
31
31
  declare_double('Double', *args)
32
32
  end
33
33
 
34
- # Effectively an alias for [double](#double-instance_method).
34
+ # Deprecated: Use [double](#double-instance_method).
35
35
  def mock(*args)
36
+ RSpec.deprecate "mock", :replacement => "double"
36
37
  declare_double('Mock', *args)
37
38
  end
38
39
 
39
- # Effectively an alias for [double](#double-instance_method).
40
+ # Deprecated: Use [double](#double-instance_method).
40
41
  def stub(*args)
42
+ RSpec.deprecate "stub", :replacement => "double"
41
43
  declare_double('Stub', *args)
42
44
  end
43
45
 
@@ -47,7 +49,7 @@ module RSpec
47
49
  # nil. This is to prevent false-positives and to catch potential bugs
48
50
  # early on.
49
51
  def allow_message_expectations_on_nil
50
- Proxy.allow_message_expectations_on_nil
52
+ RSpec::Mocks.space.proxy_for(nil).warn_about_expectations = false
51
53
  end
52
54
 
53
55
  # Stubs the named constant with the given value.
@@ -107,6 +109,36 @@ module RSpec
107
109
  ConstantMutator.hide(constant_name)
108
110
  end
109
111
 
112
+ # Verifies that the given object received the expected message during the
113
+ # course of the test. The method must have previously been stubbed in
114
+ # order for messages to be verified.
115
+ #
116
+ # Stubbing and verifying messages received in this way implements the
117
+ # Test Spy pattern.
118
+ #
119
+ # @param method_name [Symbol] name of the method expected to have been
120
+ # called.
121
+ #
122
+ # @example
123
+ #
124
+ # invitation = double('invitation', accept: true)
125
+ # user.accept_invitation(invitation)
126
+ # expect(invitation).to have_received(:accept)
127
+ #
128
+ # # You can also use most message expectations:
129
+ # expect(invitation).to have_received(:accept).with(mailer).once
130
+ def have_received(method_name)
131
+ Matchers::HaveReceived.new(method_name)
132
+ end
133
+
134
+ def self.included(klass)
135
+ klass.class_eval do
136
+ # This gets mixed in so that if `RSpec::Matchers` is included in
137
+ # `klass` later, it's definition of `expect` will take precedence.
138
+ include ExpectHost unless method_defined?(:expect)
139
+ end
140
+ end
141
+
110
142
  private
111
143
 
112
144
  def declare_double(declared_as, *args)
@@ -115,6 +147,10 @@ module RSpec
115
147
  RSpec::Mocks::Mock.new(*args)
116
148
  end
117
149
 
150
+ # This module exists to host the `expect` method for cases where
151
+ # rspec-mocks is used w/o rspec-expectations.
152
+ module ExpectHost
153
+ end
118
154
  end
119
155
  end
120
156
  end
@@ -2,18 +2,12 @@ module Marshal
2
2
  class << self
3
3
  def dump_with_mocks(*args)
4
4
  object = args.shift
5
- return dump_without_mocks(*args.unshift(object)) unless object.instance_variable_defined?(:@mock_proxy)
6
5
 
7
- mp = object.instance_variable_get(:@mock_proxy)
8
- return dump_without_mocks(*args.unshift(object)) unless mp.is_a?(::RSpec::Mocks::Proxy)
9
-
10
- object.__send__(:remove_instance_variable, :@mock_proxy)
11
-
12
- begin
13
- dump_without_mocks(*args.unshift(object.dup))
14
- ensure
15
- object.instance_variable_set(:@mock_proxy,mp)
6
+ if ( ::RSpec::Mocks.space && !::RSpec::Mocks.space.registered?(object) ) || NilClass === object
7
+ return dump_without_mocks(*args.unshift(object))
16
8
  end
9
+
10
+ dump_without_mocks(*args.unshift(object.dup))
17
11
  end
18
12
 
19
13
  alias_method :dump_without_mocks, :dump
@@ -2,13 +2,14 @@
2
2
  # supports wrapping rspec's mocking functionality without invading every
3
3
  # object in the system.
4
4
 
5
- require 'rspec/mocks/configuration'
5
+ require 'rspec/mocks/deprecation'
6
6
  require 'rspec/mocks/extensions/instance_exec'
7
7
  require 'rspec/mocks/instance_method_stasher'
8
8
  require 'rspec/mocks/method_double'
9
- require 'rspec/mocks/methods'
10
9
  require 'rspec/mocks/argument_matchers'
10
+ require 'rspec/mocks/example_methods'
11
11
  require 'rspec/mocks/proxy'
12
+ require 'rspec/mocks/proxy_for_nil'
12
13
  require 'rspec/mocks/test_double'
13
14
  require 'rspec/mocks/mock'
14
15
  require 'rspec/mocks/argument_list_matcher'
@@ -17,6 +18,17 @@ require 'rspec/mocks/order_group'
17
18
  require 'rspec/mocks/errors'
18
19
  require 'rspec/mocks/error_generator'
19
20
  require 'rspec/mocks/space'
20
- require 'rspec/mocks/serialization'
21
- require 'rspec/mocks/any_instance'
21
+ require 'rspec/mocks/extensions/marshal'
22
+ require 'rspec/mocks/any_instance/chain'
23
+ require 'rspec/mocks/any_instance/stub_chain'
24
+ require 'rspec/mocks/any_instance/stub_chain_chain'
25
+ require 'rspec/mocks/any_instance/expectation_chain'
26
+ require 'rspec/mocks/any_instance/message_chains'
27
+ require 'rspec/mocks/any_instance/recorder'
22
28
  require 'rspec/mocks/mutate_const'
29
+ require 'rspec/mocks/matchers/have_received'
30
+ require 'rspec/mocks/matchers/receive'
31
+ require 'rspec/mocks/stub_chain'
32
+ require 'rspec/mocks/targets'
33
+ require 'rspec/mocks/syntax'
34
+ require 'rspec/mocks/configuration'
@@ -75,6 +75,9 @@ module RSpec
75
75
  def restore
76
76
  return unless @method_is_stashed
77
77
 
78
+ if @klass.__send__(:method_defined?, @method)
79
+ @klass.__send__(:undef_method, @method)
80
+ end
78
81
  @klass.__send__(:alias_method, @method, stashed_method_name)
79
82
  @klass.__send__(:remove_method, stashed_method_name)
80
83
  @method_is_stashed = false
@@ -0,0 +1,93 @@
1
+ module RSpec
2
+ module Mocks
3
+ module Matchers
4
+ class HaveReceived
5
+ COUNT_CONSTRAINTS = %w(exactly at_least at_most times once twice)
6
+ ARGS_CONSTRAINTS = %w(with)
7
+ CONSTRAINTS = COUNT_CONSTRAINTS + ARGS_CONSTRAINTS
8
+
9
+ def initialize(method_name)
10
+ @method_name = method_name
11
+ @constraints = []
12
+ @subject = nil
13
+ end
14
+
15
+ def matches?(subject)
16
+ @subject = subject
17
+ @expectation = expect
18
+ expected_messages_received?
19
+ end
20
+
21
+ def does_not_match?(subject)
22
+ @subject = subject
23
+ ensure_count_unconstrained
24
+ @expectation = expect.never
25
+ expected_messages_received?
26
+ end
27
+
28
+ def failure_message
29
+ generate_failure_message
30
+ end
31
+
32
+ def negative_failure_message
33
+ generate_failure_message
34
+ end
35
+
36
+ def description
37
+ expect.description
38
+ end
39
+
40
+ CONSTRAINTS.each do |expectation|
41
+ define_method expectation do |*args|
42
+ @constraints << [expectation, *args]
43
+ self
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def expect
50
+ expectation = mock_proxy.build_expectation(@method_name)
51
+ apply_constraints_to expectation
52
+ expectation
53
+ end
54
+
55
+ def apply_constraints_to(expectation)
56
+ @constraints.each do |constraint|
57
+ expectation.send(*constraint)
58
+ end
59
+ end
60
+
61
+ def ensure_count_unconstrained
62
+ if count_constraint
63
+ raise RSpec::Mocks::MockExpectationError,
64
+ "can't use #{count_constraint} when negative"
65
+ end
66
+ end
67
+
68
+ def count_constraint
69
+ @constraints.map(&:first).detect do |constraint|
70
+ COUNT_CONSTRAINTS.include?(constraint)
71
+ end
72
+ end
73
+
74
+ def generate_failure_message
75
+ mock_proxy.check_for_unexpected_arguments(@expectation)
76
+ @expectation.generate_error
77
+ rescue RSpec::Mocks::MockExpectationError => error
78
+ error.message
79
+ end
80
+
81
+ def expected_messages_received?
82
+ mock_proxy.replay_received_message_on @expectation
83
+ @expectation.expected_messages_received?
84
+ end
85
+
86
+ def mock_proxy
87
+ RSpec::Mocks.proxy_for(@subject)
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+