rr 0.3.11 → 0.4.0

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 (150) hide show
  1. data/CHANGES +8 -3
  2. data/README +130 -39
  3. data/Rakefile +6 -5
  4. data/lib/rr.rb +8 -8
  5. data/lib/rr/adapters/rr_methods.rb +228 -0
  6. data/lib/rr/adapters/rspec.rb +1 -1
  7. data/lib/rr/adapters/test_unit.rb +1 -1
  8. data/lib/rr/double.rb +294 -89
  9. data/lib/rr/{scenario_creator.rb → double_creator.rb} +65 -66
  10. data/lib/rr/{scenario_definition.rb → double_definition.rb} +36 -36
  11. data/lib/rr/{scenario_definition_builder.rb → double_definition_builder.rb} +3 -3
  12. data/lib/rr/double_insertion.rb +132 -0
  13. data/lib/rr/{scenario_matches.rb → double_matches.rb} +2 -2
  14. data/lib/rr/{scenario_method_proxy.rb → double_method_proxy.rb} +2 -2
  15. data/lib/rr/errors/argument_equality_error.rb +3 -3
  16. data/lib/rr/errors/rr_error.rb +13 -13
  17. data/lib/rr/errors/scenario_definition_error.rb +3 -3
  18. data/lib/rr/errors/scenario_not_found_error.rb +3 -3
  19. data/lib/rr/errors/scenario_order_error.rb +3 -3
  20. data/lib/rr/errors/times_called_error.rb +3 -3
  21. data/lib/rr/expectations/any_argument_expectation.rb +1 -1
  22. data/lib/rr/expectations/argument_equality_expectation.rb +1 -1
  23. data/lib/rr/expectations/times_called_expectation.rb +1 -1
  24. data/lib/rr/hash_with_object_id_key.rb +1 -1
  25. data/lib/rr/space.rb +40 -40
  26. data/lib/rr/times_called_matchers/any_times_matcher.rb +13 -13
  27. data/lib/rr/times_called_matchers/at_least_matcher.rb +11 -11
  28. data/lib/rr/times_called_matchers/at_most_matcher.rb +16 -16
  29. data/lib/rr/times_called_matchers/integer_matcher.rb +13 -13
  30. data/lib/rr/times_called_matchers/non_terminal.rb +21 -21
  31. data/lib/rr/times_called_matchers/proc_matcher.rb +7 -7
  32. data/lib/rr/times_called_matchers/range_matcher.rb +14 -14
  33. data/lib/rr/times_called_matchers/terminal.rb +16 -16
  34. data/lib/rr/times_called_matchers/times_called_matcher.rb +32 -32
  35. data/spec/core_spec_suite.rb +18 -0
  36. data/{examples → spec}/environment_fixture_setup.rb +0 -1
  37. data/{examples/high_level_example.rb → spec/high_level_spec.rb} +11 -11
  38. data/spec/rr/adapters/rr_methods_argument_matcher_spec.rb +67 -0
  39. data/spec/rr/adapters/rr_methods_creator_spec.rb +365 -0
  40. data/spec/rr/adapters/rr_methods_space_spec.rb +134 -0
  41. data/spec/rr/adapters/rr_methods_spec_helper.rb +11 -0
  42. data/{examples/rr/extensions/instance_methods_times_matcher_example.rb → spec/rr/adapters/rr_methods_times_matcher_spec.rb} +4 -4
  43. data/spec/rr/double/double_insertion_bind_spec.rb +78 -0
  44. data/spec/rr/double/double_insertion_dispatching_spec.rb +221 -0
  45. data/spec/rr/double/double_insertion_has_original_method_spec.rb +56 -0
  46. data/spec/rr/double/double_insertion_register_scenario_spec.rb +24 -0
  47. data/spec/rr/double/double_insertion_reset_spec.rb +89 -0
  48. data/spec/rr/double/double_insertion_spec.rb +66 -0
  49. data/spec/rr/double/double_insertion_verify_spec.rb +23 -0
  50. data/spec/rr/double_creator_spec.rb +454 -0
  51. data/{examples/rr/scenario_definition_example.rb → spec/rr/double_definition_spec.rb} +143 -143
  52. data/spec/rr/double_method_proxy_spec.rb +71 -0
  53. data/spec/rr/double_spec.rb +654 -0
  54. data/spec/rr/errors/rr_error_spec.rb +65 -0
  55. data/spec/rr/expectations/any_argument_expectation_spec.rb +47 -0
  56. data/spec/rr/expectations/anything_argument_equality_expectation_spec.rb +38 -0
  57. data/spec/rr/expectations/argument_equality_expectation_spec.rb +58 -0
  58. data/spec/rr/expectations/boolean_argument_equality_expectation_spec.rb +53 -0
  59. data/spec/rr/expectations/duck_type_argument_equality_expectation_spec.rb +71 -0
  60. data/spec/rr/expectations/is_a_argument_equality_expectation_spec.rb +51 -0
  61. data/spec/rr/expectations/numeric_argument_equality_expectation_spec.rb +47 -0
  62. data/spec/rr/expectations/range_argument_equality_expectation_spec.rb +59 -0
  63. data/spec/rr/expectations/regexp_argument_equality_expectation_spec.rb +72 -0
  64. data/spec/rr/expectations/times_called_expectation/times_called_expectation_any_times_spec.rb +43 -0
  65. data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_least_spec.rb +67 -0
  66. data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_most_spec.rb +71 -0
  67. data/spec/rr/expectations/times_called_expectation/times_called_expectation_helper.rb +21 -0
  68. data/spec/rr/expectations/times_called_expectation/times_called_expectation_integer_spec.rb +103 -0
  69. data/spec/rr/expectations/times_called_expectation/times_called_expectation_proc_spec.rb +79 -0
  70. data/spec/rr/expectations/times_called_expectation/times_called_expectation_range_spec.rb +81 -0
  71. data/spec/rr/expectations/times_called_expectation/times_called_expectation_spec.rb +40 -0
  72. data/spec/rr/rspec/rspec_adapter_spec.rb +65 -0
  73. data/spec/rr/rspec/rspec_backtrace_tweaking_spec.rb +52 -0
  74. data/spec/rr/rspec/rspec_usage_spec.rb +67 -0
  75. data/spec/rr/space/hash_with_object_id_key_spec.rb +88 -0
  76. data/spec/rr/space/space_create_spec.rb +278 -0
  77. data/spec/rr/space/space_helper.rb +7 -0
  78. data/spec/rr/space/space_register_spec.rb +32 -0
  79. data/spec/rr/space/space_reset_spec.rb +131 -0
  80. data/spec/rr/space/space_spec.rb +32 -0
  81. data/spec/rr/space/space_verify_spec.rb +181 -0
  82. data/{examples → spec}/rr/test_unit/test_helper.rb +1 -1
  83. data/{examples → spec}/rr/test_unit/test_unit_backtrace_test.rb +0 -0
  84. data/{examples → spec}/rr/test_unit/test_unit_integration_test.rb +4 -4
  85. data/spec/rr/times_called_matchers/any_times_matcher_spec.rb +47 -0
  86. data/spec/rr/times_called_matchers/at_least_matcher_spec.rb +55 -0
  87. data/spec/rr/times_called_matchers/at_most_matcher_spec.rb +70 -0
  88. data/spec/rr/times_called_matchers/integer_matcher_spec.rb +70 -0
  89. data/spec/rr/times_called_matchers/proc_matcher_spec.rb +55 -0
  90. data/spec/rr/times_called_matchers/range_matcher_spec.rb +76 -0
  91. data/spec/rr/times_called_matchers/times_called_matcher_spec.rb +118 -0
  92. data/spec/rspec_spec_suite.rb +16 -0
  93. data/spec/spec_helper.rb +9 -0
  94. data/{examples/example_suite.rb → spec/spec_suite.rb} +3 -3
  95. data/{examples/test_unit_example_suite.rb → spec/test_unit_spec_suite.rb} +0 -0
  96. metadata +93 -93
  97. data/examples/core_example_suite.rb +0 -31
  98. data/examples/example_helper.rb +0 -9
  99. data/examples/rr/double/double_bind_example.rb +0 -70
  100. data/examples/rr/double/double_dispatching_example.rb +0 -236
  101. data/examples/rr/double/double_example.rb +0 -66
  102. data/examples/rr/double/double_has_original_method_example.rb +0 -56
  103. data/examples/rr/double/double_register_scenario_example.rb +0 -24
  104. data/examples/rr/double/double_reset_example.rb +0 -89
  105. data/examples/rr/double/double_verify_example.rb +0 -23
  106. data/examples/rr/errors/rr_error_example.rb +0 -65
  107. data/examples/rr/expectations/any_argument_expectation_example.rb +0 -52
  108. data/examples/rr/expectations/anything_argument_equality_expectation_example.rb +0 -38
  109. data/examples/rr/expectations/argument_equality_expectation_example.rb +0 -62
  110. data/examples/rr/expectations/boolean_argument_equality_expectation_example.rb +0 -48
  111. data/examples/rr/expectations/duck_type_argument_equality_expectation_example.rb +0 -67
  112. data/examples/rr/expectations/is_a_argument_equality_expectation_example.rb +0 -50
  113. data/examples/rr/expectations/numeric_argument_equality_expectation_example.rb +0 -46
  114. data/examples/rr/expectations/range_argument_equality_expectation_example.rb +0 -59
  115. data/examples/rr/expectations/regexp_argument_equality_expectation_example.rb +0 -67
  116. data/examples/rr/expectations/times_called_expectation/times_called_expectation_any_times_example.rb +0 -50
  117. data/examples/rr/expectations/times_called_expectation/times_called_expectation_at_least_example.rb +0 -73
  118. data/examples/rr/expectations/times_called_expectation/times_called_expectation_at_most_example.rb +0 -77
  119. data/examples/rr/expectations/times_called_expectation/times_called_expectation_example.rb +0 -42
  120. data/examples/rr/expectations/times_called_expectation/times_called_expectation_helper.rb +0 -20
  121. data/examples/rr/expectations/times_called_expectation/times_called_expectation_integer_example.rb +0 -111
  122. data/examples/rr/expectations/times_called_expectation/times_called_expectation_proc_example.rb +0 -88
  123. data/examples/rr/expectations/times_called_expectation/times_called_expectation_range_example.rb +0 -90
  124. data/examples/rr/extensions/instance_methods_argument_matcher_example.rb +0 -65
  125. data/examples/rr/extensions/instance_methods_creator_example.rb +0 -363
  126. data/examples/rr/extensions/instance_methods_example_helper.rb +0 -11
  127. data/examples/rr/extensions/instance_methods_space_example.rb +0 -122
  128. data/examples/rr/rspec/rspec_adapter_example.rb +0 -63
  129. data/examples/rr/rspec/rspec_backtrace_tweaking_example.rb +0 -36
  130. data/examples/rr/rspec/rspec_usage_example.rb +0 -65
  131. data/examples/rr/scenario_creator_example.rb +0 -459
  132. data/examples/rr/scenario_example.rb +0 -701
  133. data/examples/rr/scenario_method_proxy_example.rb +0 -71
  134. data/examples/rr/space/hash_with_object_id_key_example.rb +0 -86
  135. data/examples/rr/space/space_create_example.rb +0 -278
  136. data/examples/rr/space/space_example.rb +0 -29
  137. data/examples/rr/space/space_helper.rb +0 -7
  138. data/examples/rr/space/space_register_example.rb +0 -32
  139. data/examples/rr/space/space_reset_example.rb +0 -120
  140. data/examples/rr/space/space_verify_example.rb +0 -169
  141. data/examples/rr/times_called_matchers/any_times_matcher_example.rb +0 -63
  142. data/examples/rr/times_called_matchers/at_least_matcher_example.rb +0 -70
  143. data/examples/rr/times_called_matchers/at_most_matcher_example.rb +0 -85
  144. data/examples/rr/times_called_matchers/integer_matcher_example.rb +0 -91
  145. data/examples/rr/times_called_matchers/proc_matcher_example.rb +0 -77
  146. data/examples/rr/times_called_matchers/range_matcher_example.rb +0 -97
  147. data/examples/rr/times_called_matchers/times_called_matcher_example.rb +0 -53
  148. data/examples/rspec_example_suite.rb +0 -25
  149. data/lib/rr/extensions/instance_methods.rb +0 -228
  150. data/lib/rr/scenario.rb +0 -337
@@ -1,8 +1,8 @@
1
1
  module RR
2
- # RR::Scenario is the use case for a method call.
2
+ # RR::Double is the use case for a method call.
3
3
  # It has the ArgumentEqualityExpectation, TimesCalledExpectation,
4
4
  # and the implementation.
5
- class ScenarioDefinition
5
+ class DoubleDefinition #:nodoc:
6
6
  ORIGINAL_METHOD = Object.new
7
7
  attr_accessor :times_called,
8
8
  :argument_expectation,
@@ -23,7 +23,7 @@ module RR
23
23
  returns_block_callback_strategy!
24
24
  end
25
25
 
26
- # Scenario#with sets the expectation that the Scenario will receive
26
+ # Double#with sets the expectation that the Double will receive
27
27
  # the passed in arguments.
28
28
  #
29
29
  # Passing in a block sets the return value.
@@ -35,7 +35,7 @@ module RR
35
35
  self
36
36
  end
37
37
 
38
- # Scenario#with_any_args sets the expectation that the Scenario can receive
38
+ # Double#with_any_args sets the expectation that the Double can receive
39
39
  # any arguments.
40
40
  #
41
41
  # Passing in a block sets the return value.
@@ -47,7 +47,7 @@ module RR
47
47
  self
48
48
  end
49
49
 
50
- # Scenario#with_no_args sets the expectation that the Scenario will receive
50
+ # Double#with_no_args sets the expectation that the Double will receive
51
51
  # no arguments.
52
52
  #
53
53
  # Passing in a block sets the return value.
@@ -59,7 +59,7 @@ module RR
59
59
  self
60
60
  end
61
61
 
62
- # Scenario#never sets the expectation that the Scenario will never be
62
+ # Double#never sets the expectation that the Double will never be
63
63
  # called.
64
64
  #
65
65
  # This method does not accept a block because it will never be called.
@@ -70,7 +70,7 @@ module RR
70
70
  self
71
71
  end
72
72
 
73
- # Scenario#once sets the expectation that the Scenario will be called
73
+ # Double#once sets the expectation that the Double will be called
74
74
  # 1 time.
75
75
  #
76
76
  # Passing in a block sets the return value.
@@ -82,7 +82,7 @@ module RR
82
82
  self
83
83
  end
84
84
 
85
- # Scenario#twice sets the expectation that the Scenario will be called
85
+ # Double#twice sets the expectation that the Double will be called
86
86
  # 2 times.
87
87
  #
88
88
  # Passing in a block sets the return value.
@@ -94,7 +94,7 @@ module RR
94
94
  self
95
95
  end
96
96
 
97
- # Scenario#at_least sets the expectation that the Scenario
97
+ # Double#at_least sets the expectation that the Double
98
98
  # will be called at least n times.
99
99
  # It works by creating a TimesCalledExpectation.
100
100
  #
@@ -107,7 +107,7 @@ module RR
107
107
  self
108
108
  end
109
109
 
110
- # Scenario#at_most allows sets the expectation that the Scenario
110
+ # Double#at_most allows sets the expectation that the Double
111
111
  # will be called at most n times.
112
112
  # It works by creating a TimesCalledExpectation.
113
113
  #
@@ -120,9 +120,9 @@ module RR
120
120
  self
121
121
  end
122
122
 
123
- # Scenario#any_number_of_times sets an that the Scenario will be called
123
+ # Double#any_number_of_times sets an that the Double will be called
124
124
  # any number of times. This effectively removes the times called expectation
125
- # from the Scenarion
125
+ # from the Doublen
126
126
  #
127
127
  # Passing in a block sets the return value.
128
128
  #
@@ -133,7 +133,7 @@ module RR
133
133
  self
134
134
  end
135
135
 
136
- # Scenario#times creates an TimesCalledExpectation of the passed
136
+ # Double#times creates an TimesCalledExpectation of the passed
137
137
  # in number.
138
138
  #
139
139
  # Passing in a block sets the return value.
@@ -145,7 +145,7 @@ module RR
145
145
  self
146
146
  end
147
147
 
148
- # Scenario#ordered sets the Scenario to have an ordered
148
+ # Double#ordered sets the Double to have an ordered
149
149
  # expectation.
150
150
  #
151
151
  # Passing in a block sets the return value.
@@ -153,10 +153,10 @@ module RR
153
153
  # mock(subject).method_name.ordered {return_value}
154
154
  def ordered(&returns)
155
155
  raise(
156
- Errors::ScenarioDefinitionError,
157
- "Scenario Definitions must have a dedicated Scenario to be ordered. " <<
156
+ Errors::DoubleDefinitionError,
157
+ "Double Definitions must have a dedicated Double to be ordered. " <<
158
158
  "For example, using instance_of does not allow ordered to be used. " <<
159
- "probe the class's #new method instead."
159
+ "proxy the class's #new method instead."
160
160
  ) unless @scenario
161
161
  @ordered = true
162
162
  @space.ordered_scenarios << @scenario unless @space.ordered_scenarios.include?(@scenario)
@@ -164,17 +164,17 @@ module RR
164
164
  self
165
165
  end
166
166
 
167
- # Scenario#ordered? returns true when the Scenario is ordered.
167
+ # Double#ordered? returns true when the Double is ordered.
168
168
  #
169
169
  # mock(subject).method_name.ordered?
170
170
  def ordered?
171
171
  @ordered
172
172
  end
173
173
 
174
- # Scenario#yields sets the Scenario to invoke a passed in block when
175
- # the Scenario is called.
174
+ # Double#yields sets the Double to invoke a passed in block when
175
+ # the Double is called.
176
176
  # An Expection will be raised if no block is passed in when the
177
- # Scenario is called.
177
+ # Double is called.
178
178
  #
179
179
  # Passing in a block sets the return value.
180
180
  #
@@ -186,29 +186,29 @@ module RR
186
186
  self
187
187
  end
188
188
 
189
- # Scenario#after_call creates a callback that occurs after call
189
+ # Double#after_call creates a callback that occurs after call
190
190
  # is called. The passed in block receives the return value of
191
- # the Scenario being called.
191
+ # the Double being called.
192
192
  # An Expection will be raised if no block is passed in.
193
193
  #
194
194
  # mock(subject).method_name {return_value}.after_call {|return_value|}
195
195
  # subject.method_name # return_value
196
196
  #
197
- # This feature is built into probes.
198
- # probe(User).find('1') {|user| mock(user).valid? {false}}
197
+ # This feature is built into proxys.
198
+ # mock.proxy(User).find('1') {|user| mock(user).valid? {false}}
199
199
  def after_call(&block)
200
200
  raise ArgumentError, "after_call expects a block" unless block
201
201
  @after_call_value = block
202
202
  self
203
203
  end
204
204
 
205
- # Scenario#returns accepts an argument value or a block.
205
+ # Double#returns accepts an argument value or a block.
206
206
  # It will raise an ArgumentError if both are passed in.
207
207
  #
208
- # Passing in a block causes Scenario to return the return value of
208
+ # Passing in a block causes Double to return the return value of
209
209
  # the passed in block.
210
210
  #
211
- # Passing in an argument causes Scenario to return the argument.
211
+ # Passing in an argument causes Double to return the argument.
212
212
  def returns(value=nil, &implementation)
213
213
  if value && implementation
214
214
  raise ArgumentError, "returns cannot accept both an argument and a block"
@@ -221,9 +221,9 @@ module RR
221
221
  self
222
222
  end
223
223
 
224
- # Scenario#implemented_by sets the implementation of the Scenario.
224
+ # Double#implemented_by sets the implementation of the Double.
225
225
  # This method takes a Proc or a Method. Passing in a Method allows
226
- # the Scenario to accept blocks.
226
+ # the Double to accept blocks.
227
227
  #
228
228
  # obj = Object.new
229
229
  # def obj.foobar
@@ -235,9 +235,9 @@ module RR
235
235
  self
236
236
  end
237
237
 
238
- # Scenario#implemented_by_original_method sets the implementation
239
- # of the Scenario to be the original method.
240
- # This is primarily used with probes.
238
+ # Double#implemented_by_original_method sets the implementation
239
+ # of the Double to be the original method.
240
+ # This is primarily used with proxyies.
241
241
  #
242
242
  # obj = Object.new
243
243
  # def obj.foobar
@@ -250,14 +250,14 @@ module RR
250
250
  self
251
251
  end
252
252
 
253
- # Scenario#exact_match? returns true when the passed in arguments
253
+ # Double#exact_match? returns true when the passed in arguments
254
254
  # exactly match the ArgumentEqualityExpectation arguments.
255
255
  def exact_match?(*arguments)
256
256
  return false unless @argument_expectation
257
257
  @argument_expectation.exact_match?(*arguments)
258
258
  end
259
259
 
260
- # Scenario#wildcard_match? returns true when the passed in arguments
260
+ # Double#wildcard_match? returns true when the passed in arguments
261
261
  # wildcard match the ArgumentEqualityExpectation arguments.
262
262
  def wildcard_match?(*arguments)
263
263
  return false unless @argument_expectation
@@ -269,7 +269,7 @@ module RR
269
269
  @times_matcher.terminal?
270
270
  end
271
271
 
272
- # The Arguments that this Scenario expects
272
+ # The Arguments that this Double expects
273
273
  def expected_arguments
274
274
  return [] unless argument_expectation
275
275
  argument_expectation.expected_arguments
@@ -1,5 +1,5 @@
1
1
  module RR
2
- class ScenarioDefinitionBuilder
2
+ class DoubleDefinitionBuilder #:nodoc:
3
3
  attr_reader :definition
4
4
 
5
5
  def initialize(definition, args, handler)
@@ -17,7 +17,7 @@ module RR
17
17
  permissive_argument!
18
18
  end
19
19
 
20
- def do_not_call!
20
+ def dont_allow!
21
21
  @definition.never
22
22
  permissive_argument!
23
23
  reimplementation!
@@ -35,7 +35,7 @@ module RR
35
35
  @definition.returns(&@handler)
36
36
  end
37
37
 
38
- def probe!
38
+ def proxy!
39
39
  @definition.after_call_block_callback_strategy!
40
40
  @definition.implemented_by_original_method
41
41
  @definition.after_call(&@handler) if @handler
@@ -0,0 +1,132 @@
1
+ module RR
2
+ # RR::DoubleInsertion is the binding of an object and a method.
3
+ # A double_insertion has 0 to many Double objects. Each Double
4
+ # has Argument Expectations and Times called Expectations.
5
+ class DoubleInsertion
6
+ MethodArguments = Struct.new(:arguments, :block)
7
+ attr_reader :space, :object, :method_name, :scenarios
8
+
9
+ def initialize(space, object, method_name)
10
+ @space = space
11
+ @object = object
12
+ @method_name = method_name.to_sym
13
+ if object_has_method?(method_name)
14
+ meta.send(:alias_method, original_method_name, method_name)
15
+ end
16
+ @scenarios = []
17
+ end
18
+
19
+ # RR::DoubleInsertion#register_scenario adds the passed in Double
20
+ # into this DoubleInsertion's list of Double objects.
21
+ def register_scenario(scenario)
22
+ @scenarios << scenario
23
+ end
24
+
25
+ # RR::DoubleInsertion#bind injects a method that acts as a dispatcher
26
+ # that dispatches to the matching Double when the method
27
+ # is called.
28
+ def bind
29
+ define_implementation_placeholder
30
+ returns_method = <<-METHOD
31
+ def #{@method_name}(*args, &block)
32
+ arguments = MethodArguments.new(args, block)
33
+ #{placeholder_name}(arguments)
34
+ end
35
+ METHOD
36
+ meta.class_eval(returns_method, __FILE__, __LINE__ - 5)
37
+ end
38
+
39
+ # RR::DoubleInsertion#verify verifies each Double
40
+ # TimesCalledExpectation are met.
41
+ def verify
42
+ @scenarios.each do |scenario|
43
+ scenario.verify
44
+ end
45
+ end
46
+
47
+ # RR::DoubleInsertion#reset removes the injected dispatcher method.
48
+ # It binds the original method implementation on the object
49
+ # if one exists.
50
+ def reset
51
+ meta.send(:remove_method, placeholder_name)
52
+ if object_has_original_method?
53
+ meta.send(:alias_method, @method_name, original_method_name)
54
+ meta.send(:remove_method, original_method_name)
55
+ else
56
+ meta.send(:remove_method, @method_name)
57
+ end
58
+ end
59
+
60
+ def call_original_method(*args, &block)
61
+ @object.__send__(original_method_name, *args, &block)
62
+ end
63
+
64
+ def object_has_original_method?
65
+ object_has_method?(original_method_name)
66
+ end
67
+
68
+ protected
69
+ def define_implementation_placeholder
70
+ me = self
71
+ meta.send(:define_method, placeholder_name) do |arguments|
72
+ me.send(:call_method, arguments.arguments, arguments.block)
73
+ end
74
+ end
75
+
76
+ def call_method(args, block)
77
+ if scenario = find_scenario_to_attempt(args)
78
+ return scenario.call(self, *args, &block)
79
+ end
80
+ scenario_not_found_error(*args)
81
+ end
82
+
83
+ def find_scenario_to_attempt(args)
84
+ matches = DoubleMatches.new(@scenarios).find_all_matches!(args)
85
+
86
+ unless matches.exact_terminal_scenarios_to_attempt.empty?
87
+ return matches.exact_terminal_scenarios_to_attempt.first
88
+ end
89
+
90
+ unless matches.exact_non_terminal_scenarios_to_attempt.empty?
91
+ return matches.exact_non_terminal_scenarios_to_attempt.last
92
+ end
93
+
94
+ unless matches.wildcard_terminal_scenarios_to_attempt.empty?
95
+ return matches.wildcard_terminal_scenarios_to_attempt.first
96
+ end
97
+
98
+ unless matches.wildcard_non_terminal_scenarios_to_attempt.empty?
99
+ return matches.wildcard_non_terminal_scenarios_to_attempt.last
100
+ end
101
+
102
+ unless matches.matching_scenarios.empty?
103
+ # This will raise a TimesCalledError
104
+ return matches.matching_scenarios.first
105
+ end
106
+
107
+ return nil
108
+ end
109
+
110
+ def scenario_not_found_error(*args)
111
+ message = "Unexpected method invocation #{Double.formatted_name(@method_name, args)}, expected\n"
112
+ message << Double.list_message_part(@scenarios)
113
+ raise Errors::DoubleNotFoundError, message
114
+ end
115
+
116
+ def placeholder_name
117
+ "__rr__#{@method_name}"
118
+ end
119
+
120
+ def original_method_name
121
+ "__rr__original_#{@method_name}"
122
+ end
123
+
124
+ def object_has_method?(method_name)
125
+ @object.methods.include?(method_name.to_s) || @object.respond_to?(method_name)
126
+ end
127
+
128
+ def meta
129
+ (class << @object; self; end)
130
+ end
131
+ end
132
+ end
@@ -1,11 +1,11 @@
1
1
  module RR
2
- class ScenarioMatches
2
+ class DoubleMatches
3
3
  attr_reader :matching_scenarios,
4
4
  :exact_terminal_scenarios_to_attempt,
5
5
  :exact_non_terminal_scenarios_to_attempt,
6
6
  :wildcard_terminal_scenarios_to_attempt,
7
7
  :wildcard_non_terminal_scenarios_to_attempt
8
- def initialize(scenarios)
8
+ def initialize(scenarios) #:nodoc:
9
9
  @scenarios = scenarios
10
10
  @matching_scenarios = []
11
11
  @exact_terminal_scenarios_to_attempt = []
@@ -1,6 +1,6 @@
1
1
  module RR
2
- class ScenarioMethodProxy
3
- def initialize(space, creator, object, &block)
2
+ class DoubleMethodProxy
3
+ def initialize(space, creator, object, &block) #:nodoc:
4
4
  @space = space
5
5
  @creator = creator
6
6
  @object = object
@@ -1,6 +1,6 @@
1
1
  module RR
2
- module Errors
3
- class ArgumentEqualityError < RRError
2
+ module Errors
3
+ class ArgumentEqualityError < RRError
4
+ end
4
5
  end
5
- end
6
6
  end
@@ -1,20 +1,20 @@
1
1
  module RR
2
- module Errors
3
- BACKTRACE_IDENTIFIER = /lib\/rr/
2
+ module Errors
3
+ BACKTRACE_IDENTIFIER = /lib\/rr/
4
4
 
5
- class RRError < RuntimeError
6
- attr_writer :backtrace
7
- def backtrace
8
- original_backtrace = (@backtrace) ? @backtrace : super
9
- return original_backtrace unless RR::Space.trim_backtrace
5
+ class RRError < RuntimeError
6
+ attr_writer :backtrace
7
+ def backtrace
8
+ original_backtrace = (@backtrace) ? @backtrace : super
9
+ return original_backtrace unless RR::Space.trim_backtrace
10
10
 
11
- return original_backtrace unless original_backtrace.respond_to?(:each)
12
- new_backtrace = []
13
- original_backtrace.each do |line|
14
- new_backtrace << line unless line =~ BACKTRACE_IDENTIFIER
11
+ return original_backtrace unless original_backtrace.respond_to?(:each)
12
+ new_backtrace = []
13
+ original_backtrace.each do |line|
14
+ new_backtrace << line unless line =~ BACKTRACE_IDENTIFIER
15
+ end
16
+ new_backtrace
15
17
  end
16
- new_backtrace
17
18
  end
18
19
  end
19
- end
20
20
  end