rr 0.3.11 → 0.4.0

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