rspec-mocks 2.13.1 → 2.14.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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
+