rr 1.0.4 → 1.0.5.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/CHANGES.md +376 -0
- data/Gemfile +7 -10
- data/README.md +822 -0
- data/Rakefile +24 -78
- data/VERSION +1 -0
- data/lib/rr.rb +3 -0
- data/lib/rr/adapters/minitest.rb +6 -0
- data/lib/rr/adapters/rr_methods.rb +6 -10
- data/lib/rr/adapters/rspec.rb +3 -0
- data/lib/rr/adapters/rspec2.rb +30 -0
- data/lib/rr/adapters/test_unit.rb +2 -0
- data/lib/rr/double.rb +3 -2
- data/lib/rr/double_definitions/child_double_definition_create.rb +3 -2
- data/lib/rr/double_definitions/double_definition.rb +15 -13
- data/lib/rr/double_definitions/double_definition_create.rb +9 -5
- data/lib/rr/double_definitions/double_injections/any_instance_of.rb +3 -2
- data/lib/rr/double_definitions/strategies/strategy.rb +5 -4
- data/lib/rr/double_definitions/strategies/strategy_methods.rb +6 -8
- data/lib/rr/double_definitions/strategies/verification/mock.rb +3 -3
- data/lib/rr/double_matches.rb +2 -1
- data/lib/rr/expectations/argument_equality_expectation.rb +2 -2
- data/lib/rr/expectations/times_called_expectation.rb +2 -2
- data/lib/rr/injections/double_injection.rb +12 -11
- data/lib/rr/injections/injection.rb +2 -2
- data/lib/rr/injections/method_missing_injection.rb +21 -7
- data/lib/rr/injections/singleton_method_added_injection.rb +3 -1
- data/lib/rr/method_dispatches/base_method_dispatch.rb +1 -1
- data/lib/rr/method_dispatches/method_dispatch.rb +2 -1
- data/lib/rr/method_dispatches/method_missing_dispatch.rb +2 -1
- data/lib/rr/proc_from_block.rb +8 -4
- data/lib/rr/space.rb +3 -2
- data/lib/rr/times_called_matchers/times_called_matcher.rb +2 -2
- data/lib/rr/version.rb +5 -0
- data/lib/rr/wildcard_matchers/boolean.rb +2 -2
- data/spec/runner.rb +41 -0
- metadata +45 -133
- data/.gitignore +0 -10
- data/.runrc +0 -3
- data/.rvmrc +0 -2
- data/CHANGES +0 -266
- data/Gemfile.lock +0 -31
- data/README.rdoc +0 -392
- data/benchmarks/rr_benchmark.rb +0 -32
- data/benchmarks/rspec_benchmark.rb +0 -14
- data/doc/0.6.0.release.markdown +0 -81
- data/doc/todo.txt +0 -0
- data/introducting_rr.txt +0 -206
- data/rr.gemspec +0 -37
- data/spec/api/any_instance_of/all_instances_of_spec.rb +0 -12
- data/spec/api/any_instance_of/any_instance_of_spec.rb +0 -47
- data/spec/api/any_instance_of/instance_of_spec.rb +0 -12
- data/spec/api/dont_allow/dont_allow_after_stub_spec.rb +0 -14
- data/spec/api/mock/mock_spec.rb +0 -193
- data/spec/api/proxy/proxy_spec.rb +0 -86
- data/spec/api/spy/spy_spec.rb +0 -49
- data/spec/api/strong/strong_spec.rb +0 -87
- data/spec/api/stub/stub_spec.rb +0 -152
- data/spec/core_spec_suite.rb +0 -19
- data/spec/environment_fixture_setup.rb +0 -8
- data/spec/minitest_spec_suite.rb +0 -21
- data/spec/proc_from_block_spec.rb +0 -14
- data/spec/rr/adapters/rr_methods_argument_matcher_spec.rb +0 -67
- data/spec/rr/adapters/rr_methods_creator_spec.rb +0 -137
- data/spec/rr/adapters/rr_methods_space_spec.rb +0 -98
- data/spec/rr/adapters/rr_methods_spec_helper.rb +0 -11
- data/spec/rr/adapters/rr_methods_times_matcher_spec.rb +0 -13
- data/spec/rr/double_definitions/child_double_definition_creator_spec.rb +0 -112
- data/spec/rr/double_definitions/double_definition_create_blank_slate_spec.rb +0 -91
- data/spec/rr/double_definitions/double_definition_create_spec.rb +0 -443
- data/spec/rr/double_injection/double_injection_spec.rb +0 -546
- data/spec/rr/double_injection/double_injection_verify_spec.rb +0 -29
- data/spec/rr/errors/rr_error_spec.rb +0 -67
- data/spec/rr/expectations/any_argument_expectation_spec.rb +0 -47
- data/spec/rr/expectations/anything_argument_equality_expectation_spec.rb +0 -14
- data/spec/rr/expectations/argument_equality_expectation_spec.rb +0 -135
- data/spec/rr/expectations/boolean_argument_equality_expectation_spec.rb +0 -34
- data/spec/rr/expectations/hash_including_argument_equality_expectation_spec.rb +0 -82
- data/spec/rr/expectations/hash_including_spec.rb +0 -17
- data/spec/rr/expectations/satisfy_argument_equality_expectation_spec.rb +0 -59
- data/spec/rr/expectations/satisfy_spec.rb +0 -14
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_any_times_spec.rb +0 -22
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_least_spec.rb +0 -37
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_most_spec.rb +0 -43
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_helper.rb +0 -15
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_integer_spec.rb +0 -58
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_proc_spec.rb +0 -35
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_range_spec.rb +0 -39
- data/spec/rr/minitest/minitest_integration_test.rb +0 -59
- data/spec/rr/minitest/test_helper.rb +0 -7
- data/spec/rr/rspec/invocation_matcher_spec.rb +0 -279
- data/spec/rr/rspec/rspec_adapter_spec.rb +0 -63
- data/spec/rr/rspec/rspec_backtrace_tweaking_spec.rb +0 -31
- data/spec/rr/rspec/rspec_backtrace_tweaking_spec_fixture.rb +0 -11
- data/spec/rr/rspec/rspec_usage_spec.rb +0 -86
- data/spec/rr/space/hash_with_object_id_key_spec.rb +0 -88
- data/spec/rr/space/space_spec.rb +0 -596
- data/spec/rr/test_unit/test_helper.rb +0 -7
- data/spec/rr/test_unit/test_unit_backtrace_test.rb +0 -36
- data/spec/rr/test_unit/test_unit_integration_test.rb +0 -59
- data/spec/rr/times_called_matchers/any_times_matcher_spec.rb +0 -47
- data/spec/rr/times_called_matchers/at_least_matcher_spec.rb +0 -55
- data/spec/rr/times_called_matchers/at_most_matcher_spec.rb +0 -70
- data/spec/rr/times_called_matchers/integer_matcher_spec.rb +0 -70
- data/spec/rr/times_called_matchers/proc_matcher_spec.rb +0 -55
- data/spec/rr/times_called_matchers/range_matcher_spec.rb +0 -76
- data/spec/rr/times_called_matchers/times_called_matcher_spec.rb +0 -118
- data/spec/rr/wildcard_matchers/anything_spec.rb +0 -24
- data/spec/rr/wildcard_matchers/boolean_spec.rb +0 -36
- data/spec/rr/wildcard_matchers/duck_type_spec.rb +0 -52
- data/spec/rr/wildcard_matchers/is_a_spec.rb +0 -32
- data/spec/rr/wildcard_matchers/numeric_spec.rb +0 -32
- data/spec/rr/wildcard_matchers/range_spec.rb +0 -35
- data/spec/rr/wildcard_matchers/regexp_spec.rb +0 -43
- data/spec/rr_spec.rb +0 -28
- data/spec/rspec_spec_suite.rb +0 -17
- data/spec/spec.opts +0 -10
- data/spec/spec_helper.rb +0 -41
- data/spec/spec_suite.rb +0 -54
- data/spec/spy_verification_spec.rb +0 -129
- data/spec/test_unit_spec_suite.rb +0 -21
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MzZiOTU0OTRjZjQ4NTUxODZhMTNkOTAxMjg3NmZiY2E1YWZmYTE1MQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
OGFkYmIyMWRiNTg0ZTU5OTIyYmM4NDM3YzZkODAzOTJkMDg1MDIyMA==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
YzI1MDhlMDhkMDZmMWU0ODBjZjdjZDdjZjQ5ZDkwNTEyZTA4NDM2ZmI0N2Nk
|
10
|
+
MDM4MDVlOTg5NTJjYWRiYTVjMTA5NDQ2MDFiNzhmMzMyZjliZjI0NTE0MjJl
|
11
|
+
YzM0Y2RlY2I5ZjkyNmZkN2M5MzNjNjJmZTUzMTg5YjkyOWQwN2U=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
OWI5YTViOGFiMzg0YmIzYzZlNjZmZmFkMDkwMjczYWRjNmUxMDRhYjAzZjgw
|
14
|
+
MjNhNmU4YjQ1Njg3OTlkYTY3NzNmNTc1MWM0OTUzMGEyZTg0MTMzZjRmNjIy
|
15
|
+
YmUyYzU1ZjVlMmI4ZDc5ZmEzODc3OTlkYjQ1Nzg3Y2I5MWQzNGE=
|
data/CHANGES.md
ADDED
@@ -0,0 +1,376 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## 1.0.4 (2011-06-11)
|
4
|
+
|
5
|
+
* Fixed bug using workaround with leftover MethodMissingInjections
|
6
|
+
|
7
|
+
## 1.0.3 (2011-06-11)
|
8
|
+
|
9
|
+
* Eliminate usage of ObjectSpace._id2ref (Patch Evan Phoenix)
|
10
|
+
* Added minitest adapter (Patch Caleb Spare)
|
11
|
+
* Added instructions on installing the gem (Patch Gavin Miller)
|
12
|
+
* delete missing scratch.rb file from gemspec (Patch bonkydog)
|
13
|
+
|
14
|
+
## 1.0.2 (2010-11-01)
|
15
|
+
|
16
|
+
* Fixed Two calls recorded to a mock expecting only one call when called via
|
17
|
+
another mock's yield block
|
18
|
+
(http://github.com/btakita/rr/issues/closed#issue/42). Patch by Eugene Pimenov
|
19
|
+
(http://github.com/libc).
|
20
|
+
|
21
|
+
## 1.0.1 (2010-10-30)
|
22
|
+
|
23
|
+
* Removed new_instance_of for Ruby 1.9.2 compatibility. instance_of is now an
|
24
|
+
alias for any_instance_of.
|
25
|
+
* Compatible with Ruby 1.9.2
|
26
|
+
|
27
|
+
## 1.0.0 (2010-08-23)
|
28
|
+
|
29
|
+
* Added any_instance_of (aliased by all_instances_of), which binds methods
|
30
|
+
directly to the class (instead of the eigenclass).
|
31
|
+
* Subclasses of a injected class do not have their methods overridden.
|
32
|
+
* any_instance_of and new_instance_of now have a block syntax
|
33
|
+
|
34
|
+
## 0.10.11 (2010-03-22)
|
35
|
+
|
36
|
+
* Added RR.blank_slate_whitelist
|
37
|
+
* Fixed class_eval method redefinition warning in jruby
|
38
|
+
|
39
|
+
## 0.10.10 (2010-02-25)
|
40
|
+
|
41
|
+
* Suite passes for Ruby 1.9.1
|
42
|
+
|
43
|
+
## 0.10.9 (2010-02-17)
|
44
|
+
|
45
|
+
* Fixed 1.8.6 bug for real
|
46
|
+
|
47
|
+
## 0.10.8 (2010-02-16)
|
48
|
+
|
49
|
+
* Fixed 1.8.6 bug
|
50
|
+
|
51
|
+
## 0.10.7 (2010-02-15)
|
52
|
+
|
53
|
+
* Fixed issue with DoubleInjections binding to objects overriding the method
|
54
|
+
method.
|
55
|
+
|
56
|
+
## 0.10.6 (2010-02-15)
|
57
|
+
|
58
|
+
* Added MIT license
|
59
|
+
* Fixed Bug - dont_allow doesn't work when it follows stub
|
60
|
+
(http://github.com/btakita/rr/issues#issue/20)
|
61
|
+
* Fixed exception with DoubleInjections on proxy objects
|
62
|
+
(http://github.com/btakita/rr/issues#issue/24)
|
63
|
+
* Fixed Bug - Can't stub attribute methods on a BelongsToAssociation
|
64
|
+
(http://github.com/btakita/rr/issues#issue/24)
|
65
|
+
|
66
|
+
## 0.10.5 (2009-12-20)
|
67
|
+
|
68
|
+
* Fixed stack overflow caused by double include in Test::Unit adapter
|
69
|
+
[http://github.com/btakita/rr/issues#issue/16]. Identified by Dave Myron
|
70
|
+
(http://github.com/contentfree)
|
71
|
+
* Fixed warnings (Patch by Bryan Helmkamp)
|
72
|
+
|
73
|
+
## 0.10.4 (2009-09-26)
|
74
|
+
|
75
|
+
* Handle lazily defined methods (where respond_to? returns true yet the method
|
76
|
+
is not yet defined and the first call to method_missing defines the method).
|
77
|
+
This pattern is used in ActiveRecord and ActionMailer.
|
78
|
+
* Fixed warning about aliasing #instance_exec in jruby.
|
79
|
+
http://github.com/btakita/rr/issues#issue/9 (Patch by Nathan Sobo)
|
80
|
+
|
81
|
+
## 0.10.2 (2009-08-30)
|
82
|
+
|
83
|
+
* RR properly proxies subjects with private methods
|
84
|
+
[http://github.com/btakita/rr/issues/#issue/7]. Identified by Matthew
|
85
|
+
O'Connor.
|
86
|
+
|
87
|
+
## 0.10.1 (???)
|
88
|
+
|
89
|
+
* Fixed issue with DoubleInjection not invoking methods that are lazily created
|
90
|
+
[http://github.com/btakita/rr/issues/#issue/4]. Identified by davidlee
|
91
|
+
(http://github.com/davidlee)
|
92
|
+
* Fixed issue with mock.proxy and returns
|
93
|
+
[http://github.com/btakita/rr/issues/#issue/2]. Identified by trogdoro
|
94
|
+
(http://github.com/trogdoro)
|
95
|
+
|
96
|
+
## 0.10.0 (2009-06-01)
|
97
|
+
|
98
|
+
* Method is no longer invoked if respond_to? returns false. This was in place to
|
99
|
+
support ActiveRecord association proxies, and is no longer needed.
|
100
|
+
|
101
|
+
## 0.9.0 (2009-04-25)
|
102
|
+
|
103
|
+
* instance_of Doubles now apply to methods invoked in the subject's #initialize
|
104
|
+
method.
|
105
|
+
|
106
|
+
## 0.8.1 (2009-03-29)
|
107
|
+
|
108
|
+
* Fixed exception where the Subject uses method delegation via method_missing
|
109
|
+
(e.g. certain ActiveRecord AssociationProxy methods)
|
110
|
+
|
111
|
+
## 0.8.0 (2009-03-29)
|
112
|
+
|
113
|
+
* Fixed compatability issues with Ruby 1.9
|
114
|
+
* Aliased any_number_of_times with any_times
|
115
|
+
* Better error messages for have_received and assert_received matchers (Patch by
|
116
|
+
Joe Ferris)
|
117
|
+
* Better documentation on RR wilcard matchers (Patch by Phil Arnowsky)
|
118
|
+
|
119
|
+
## 0.7.1 (2009-01-16)
|
120
|
+
|
121
|
+
* Performance improvements
|
122
|
+
|
123
|
+
## 0.7.0 (2008-12-14)
|
124
|
+
|
125
|
+
* Added spies (Patchs by Joe Ferris, Michael Niessner & Mike Mangino)
|
126
|
+
* Added strongly typed reimplementation doubles (Patch by Michael Niessner)
|
127
|
+
|
128
|
+
## 0.6.2 (???)
|
129
|
+
|
130
|
+
* Fixed DoubleDefinition chaining edge cases
|
131
|
+
|
132
|
+
## 0.6.1 (???)
|
133
|
+
|
134
|
+
* DoubleDefinitionCreatorProxy definition eval block is instance_evaled when the
|
135
|
+
arity is not 1. When the arity is 1, the block is yielded with the
|
136
|
+
DoubleDefinitionCreatorProxy passed in.
|
137
|
+
|
138
|
+
## 0.6.0 (2008-10-13)
|
139
|
+
|
140
|
+
* Friendlier DoubleNotFound error message
|
141
|
+
* Implemented Double strategy creation methods (#mock, #stub, #proxy,
|
142
|
+
#instance_of, and ! equivalents) on DoubleDefinition
|
143
|
+
* Implemented hash_including matcher (Patch by Matthew O'Conner)
|
144
|
+
* Implemented satisfy matcher (Patch by Matthew O'Conner)
|
145
|
+
* Implemented DoubleDefinitionCreator#mock!, #stub!, and #dont_allow!
|
146
|
+
* Modified api to method chain Doubles
|
147
|
+
* Fix conflict with Mocha overriding Object#verify
|
148
|
+
|
149
|
+
## 0.5.0 (???)
|
150
|
+
|
151
|
+
* Method chaining Doubles (Patch by Nick Kallen)
|
152
|
+
* Chained ordered expectations (Patch by Nick Kallen)
|
153
|
+
* Space#verify_doubles can take one or more objects with DoubleInjections to be
|
154
|
+
verified
|
155
|
+
|
156
|
+
## 0.4.10 (2008-07-06)
|
157
|
+
|
158
|
+
* DoubleDefinitionCreatorProxy does not undef #object_id
|
159
|
+
* Fixed rdoc pointer to README
|
160
|
+
|
161
|
+
## 0.4.9 (2008-06-18)
|
162
|
+
|
163
|
+
* Proxying from RR module to RR::Space.instance
|
164
|
+
|
165
|
+
## 0.4.8 (2008-01-23)
|
166
|
+
|
167
|
+
* Fixed issue with Hash arguments
|
168
|
+
|
169
|
+
## 0.4.7 (2008-01-23)
|
170
|
+
|
171
|
+
* Improved error message
|
172
|
+
|
173
|
+
## 0.4.6 (2008-01-23)
|
174
|
+
|
175
|
+
* Added Double#verbose and Double#verbose?
|
176
|
+
|
177
|
+
## 0.4.5 (2008-01-15)
|
178
|
+
|
179
|
+
* Fixed doubles for == and #eql? methods
|
180
|
+
|
181
|
+
## 0.4.4 (2008-01-15)
|
182
|
+
|
183
|
+
* Doc improvements
|
184
|
+
* Methods that are not alphabetic, such as ==, can be doubles
|
185
|
+
|
186
|
+
## 0.4.3 (2008-01-07)
|
187
|
+
|
188
|
+
* Doc improvements
|
189
|
+
* Cleanup
|
190
|
+
* Finished renaming scenario to double
|
191
|
+
|
192
|
+
## 0.4.2 (2007-12-31)
|
193
|
+
|
194
|
+
* Renamed DoubleInsertion to DoubleInjection to be consistent with Mocha
|
195
|
+
terminology
|
196
|
+
|
197
|
+
## 0.4.1 (2007-12-31)
|
198
|
+
|
199
|
+
* Fixed backward compatability issues with rspec
|
200
|
+
* Renamed Space#verify_double_insertions to #verify_doubles
|
201
|
+
|
202
|
+
## 0.4.0 (2007-12-30)
|
203
|
+
|
204
|
+
* Documentation improvements
|
205
|
+
* Renamed Double to DoubleInsertion
|
206
|
+
* Renamed Scenario to Double
|
207
|
+
|
208
|
+
## 0.3.11 (2007-09-06)
|
209
|
+
|
210
|
+
* Fixed [#13724] Mock Proxy on Active Record Association proxies causes error
|
211
|
+
|
212
|
+
## 0.3.10 (2007-08-18)
|
213
|
+
|
214
|
+
* Fixed [#13139] Blocks added to proxy sets the return_value and not the
|
215
|
+
after_call callback
|
216
|
+
|
217
|
+
## 0.3.9 (2007-08-14)
|
218
|
+
|
219
|
+
* Alias probe to proxy
|
220
|
+
|
221
|
+
## 0.3.8 (2007-08-12)
|
222
|
+
|
223
|
+
* Implemented [#13009] Better error mesage from TimesCalledMatcher
|
224
|
+
|
225
|
+
## 0.3.7 (2007-08-09)
|
226
|
+
|
227
|
+
* Fixed [#12928] Reset doubles fails on Rails association proxies
|
228
|
+
|
229
|
+
## 0.3.6 (2007-08-01)
|
230
|
+
|
231
|
+
* Fixed [#12765] Issues with ObjectSpace._id2ref
|
232
|
+
|
233
|
+
## 0.3.5 (2007-07-29)
|
234
|
+
|
235
|
+
* trim_backtrace is only set for Test::Unit
|
236
|
+
|
237
|
+
## 0.3.4 (2007-07-22)
|
238
|
+
|
239
|
+
* Implemented instance_of
|
240
|
+
|
241
|
+
## 0.3.3 (2007-07-22)
|
242
|
+
|
243
|
+
* Fixed [#12495] Error Probing method_missing interaction
|
244
|
+
|
245
|
+
## 0.3.2 (2007-07-22)
|
246
|
+
|
247
|
+
* Fixed [#12486] ScenarioMethodProxy when Kernel passed into instance methods
|
248
|
+
|
249
|
+
## 0.3.1 (2007-07-22)
|
250
|
+
|
251
|
+
* Automatically require Test::Unit and Rspec adapters
|
252
|
+
|
253
|
+
## 0.3.0 (2007-07-22)
|
254
|
+
|
255
|
+
* ScenarioCreator strategy method chaining
|
256
|
+
* Removed mock_probe
|
257
|
+
* Removed stub_probe
|
258
|
+
|
259
|
+
## 0.2.5 (2007-07-21)
|
260
|
+
|
261
|
+
* mock takes method_name argument
|
262
|
+
* stub takes method_name argument
|
263
|
+
* mock_probe takes method_name argument
|
264
|
+
* stub_probe takes method_name argument
|
265
|
+
* probe takes method_name argument
|
266
|
+
* dont_allow takes method_name argument
|
267
|
+
* do_not_allow takes method_name argument
|
268
|
+
|
269
|
+
## 0.2.4 (2007-07-19)
|
270
|
+
|
271
|
+
* Space#doubles key is now the object id
|
272
|
+
* Fixed [#12402] Stubbing return value of probes fails after calling the stubbed
|
273
|
+
method two times
|
274
|
+
|
275
|
+
## 0.2.3 (2007-07-18)
|
276
|
+
|
277
|
+
* Added RRMethods#rr_verify and RRMethods#rr_reset
|
278
|
+
|
279
|
+
## 0.2.2 (2007-07-17)
|
280
|
+
|
281
|
+
* Fixed "singleton method bound for a different object"
|
282
|
+
* Doing Method aliasing again to store original method
|
283
|
+
|
284
|
+
## 0.2.1 (2007-07-17)
|
285
|
+
|
286
|
+
* Added mock_probe
|
287
|
+
* Added stub_probe
|
288
|
+
* Probe returns the return value of the passed in block, instead of ignoring its
|
289
|
+
return value
|
290
|
+
* Scenario#after_call returns the return value of the passed in block
|
291
|
+
* Not using method aliasing to store original method
|
292
|
+
* Renamed DoubleMethods to RRMethods
|
293
|
+
* Added RRMethods#mock_probe
|
294
|
+
|
295
|
+
## 0.1.15 (2007-07-17)
|
296
|
+
|
297
|
+
* Fixed [#12333] Rebinding original_methods causes blocks not to work
|
298
|
+
|
299
|
+
## 0.1.14 (2007-07-16)
|
300
|
+
|
301
|
+
* Introduced concept of Terminal and NonTerminal TimesCalledMatchers
|
302
|
+
* Doubles that can be called many times can be replaced
|
303
|
+
* Terminal Scenarios are called before NonTerminal Scenarios
|
304
|
+
* Error message tweaking
|
305
|
+
* Raise error when making a Scenarios with NonTerminal TimesMatcher Ordered
|
306
|
+
|
307
|
+
## 0.1.13 (2007-07-14)
|
308
|
+
|
309
|
+
* Fixed [#12290] Scenario#returns with false causes a return value of nil
|
310
|
+
|
311
|
+
## 0.1.12 (2007-07-14)
|
312
|
+
|
313
|
+
* Fixed bug where Creators methods are not removed when methods are defined on
|
314
|
+
Object
|
315
|
+
* Fixed [#12289] Creators methods are not removed in Rails environment
|
316
|
+
|
317
|
+
## 0.1.11 (2007-07-14)
|
318
|
+
|
319
|
+
* Fixed [#12287] AtLeastMatcher does not cause Scenario to be called
|
320
|
+
|
321
|
+
## 0.1.10 (2007-07-14)
|
322
|
+
|
323
|
+
* Fixed [#12286] AnyArgumentExpectation#expected_arguments not implemented
|
324
|
+
|
325
|
+
## 0.1.9 (2007-07-14)
|
326
|
+
|
327
|
+
* Added DoubleMethods#any_times
|
328
|
+
* Added Scenario#any_number_of_times
|
329
|
+
|
330
|
+
## 0.1.8 (2007-07-14)
|
331
|
+
|
332
|
+
* TimesCalledError Message Formatted to be on multiple lines
|
333
|
+
* ScenarioNotFoundError Message includes all Scenarios for the Double
|
334
|
+
* ScenarioOrderError shows list of remaining ordered scenarios
|
335
|
+
|
336
|
+
## 0.1.7 (2007-07-14)
|
337
|
+
|
338
|
+
* Fixed [#12194] Double#reset_doubles are not clearing Ordered Scenarios bug
|
339
|
+
* Added Space#reset
|
340
|
+
* Space#reset_doubles and Space#reset_ordered_scenarios is now protected
|
341
|
+
* Added Scenario#at_least
|
342
|
+
* Added Scenario#at_most
|
343
|
+
|
344
|
+
## 0.1.6 (2007-07-10)
|
345
|
+
|
346
|
+
* [#12120] probe allows a the return value to be intercepted
|
347
|
+
|
348
|
+
## 0.1.5 (2007-07-09)
|
349
|
+
|
350
|
+
* TimesCalledExpectation says how many times were called and how many times
|
351
|
+
called were expected on error
|
352
|
+
|
353
|
+
## 0.1.4 (2007-07-09)
|
354
|
+
|
355
|
+
* TimesCalledError prints the backtrace to where the Scenario was defined when
|
356
|
+
being verified
|
357
|
+
* Error message includes method name when Scenario is not found
|
358
|
+
|
359
|
+
## 0.1.3 (2007-07-09)
|
360
|
+
|
361
|
+
* Fixed issue where Double#placeholder_name issues when Double method name has a
|
362
|
+
! or ?
|
363
|
+
|
364
|
+
## 0.1.2 (2007-07-08)
|
365
|
+
|
366
|
+
* Scenario#returns also accepts an argument
|
367
|
+
* Implemented Scenario#yields
|
368
|
+
|
369
|
+
## 0.1.1 (2007-07-08)
|
370
|
+
|
371
|
+
* Trim the backtrace for Rspec and Test::Unit
|
372
|
+
* Rspec and Test::Unit integration fixes
|
373
|
+
|
374
|
+
## 0.1.0 (2007-07-07)
|
375
|
+
|
376
|
+
* Initial Release
|
data/Gemfile
CHANGED
@@ -1,12 +1,9 @@
|
|
1
|
-
source
|
1
|
+
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
gem "ruby-debug19", "0.11.6"
|
9
|
-
else
|
10
|
-
gem "ruby-debug", "0.10.4"
|
11
|
-
end
|
3
|
+
gem 'rake', '~> 10.0'
|
4
|
+
|
5
|
+
gem "rspec", "~> 2.13.0"
|
6
|
+
if RUBY_VERSION !~ /^1.8/
|
7
|
+
gem "minitest", "~> 4.7.0"
|
12
8
|
end
|
9
|
+
gem "session", "~> 2.4.0"
|
data/README.md
ADDED
@@ -0,0 +1,822 @@
|
|
1
|
+
# RR [![Build Status](https://secure.travis-ci.org/rr/rr.png)](http://travis-ci.org/rr/rr)
|
2
|
+
|
3
|
+
RR (Double Ruby) is a test double framework that features a rich selection of
|
4
|
+
double techniques and a terse syntax.
|
5
|
+
|
6
|
+
To get started, install RR from the command prompt:
|
7
|
+
|
8
|
+
~~~
|
9
|
+
gem install rr
|
10
|
+
~~~
|
11
|
+
|
12
|
+
|
13
|
+
## What is a test double?
|
14
|
+
|
15
|
+
A test double is a generalization of something that replaces a real object to
|
16
|
+
make it easier to test another object. It's like a stunt double for tests. The
|
17
|
+
following are test doubles:
|
18
|
+
|
19
|
+
* Mocks
|
20
|
+
* Stubs
|
21
|
+
* Fakes
|
22
|
+
* Spies
|
23
|
+
* Proxies
|
24
|
+
|
25
|
+
*Learn more: <http://xunitpatterns.com/Test%20Double.html>*
|
26
|
+
|
27
|
+
Currently RR implements mocks, stubs, proxies, and spies. Fakes usually require
|
28
|
+
custom code, so it is beyond the scope of RR.
|
29
|
+
|
30
|
+
|
31
|
+
## Using RR with your test framework
|
32
|
+
|
33
|
+
### Test::Unit
|
34
|
+
|
35
|
+
~~~ ruby
|
36
|
+
class Test::Unit::TestCase
|
37
|
+
include RR::Adapters::TestUnit
|
38
|
+
end
|
39
|
+
~~~
|
40
|
+
|
41
|
+
### RSpec
|
42
|
+
|
43
|
+
RR actually has two adapters, one for the newest version of RSpec (2) and
|
44
|
+
another for the older version (1). Currently RSpec targets RR's RSpec-1 adapter
|
45
|
+
and so until this is fixed you will need to specify the RSpec-2 adapter:
|
46
|
+
|
47
|
+
~~~ ruby
|
48
|
+
RSpec.configure do |config|
|
49
|
+
config.include(RR::Adapters::RSpec2)
|
50
|
+
end
|
51
|
+
~~~
|
52
|
+
|
53
|
+
### MiniTest / MiniSpec
|
54
|
+
|
55
|
+
~~~ ruby
|
56
|
+
class MiniTest::Unit::TestCase
|
57
|
+
include RR::Adapters::MiniTest
|
58
|
+
end
|
59
|
+
~~~
|
60
|
+
|
61
|
+
|
62
|
+
## Syntax between RR and other double/mock frameworks
|
63
|
+
|
64
|
+
### Terse syntax
|
65
|
+
|
66
|
+
One of the goals of RR is to make doubles more scannable. This is accomplished
|
67
|
+
by making the double declaration look as much as the actual method invocation as
|
68
|
+
possible. Here is RR compared to other mock frameworks:
|
69
|
+
|
70
|
+
~~~ ruby
|
71
|
+
# Flexmock
|
72
|
+
flexmock(User).should_receive(:find).with('42').and_return(jane)
|
73
|
+
# RSpec
|
74
|
+
User.should_receive(:find).with('42').and_return(jane)
|
75
|
+
# Mocha
|
76
|
+
User.expects(:find).with('42').returns { jane }
|
77
|
+
# rspec-mocks (using return value blocks)
|
78
|
+
User.should_receive(:find).with('42') { jane }
|
79
|
+
# RR
|
80
|
+
mock(User).find('42') { jane }
|
81
|
+
~~~
|
82
|
+
|
83
|
+
### Double injections (aka partial mocking)
|
84
|
+
|
85
|
+
RR utilizes a technique known as "double injection".
|
86
|
+
|
87
|
+
~~~ ruby
|
88
|
+
my_object = MyClass.new
|
89
|
+
mock(my_object).hello
|
90
|
+
~~~
|
91
|
+
|
92
|
+
Compare this with doing a mock in Mocha:
|
93
|
+
|
94
|
+
~~~ ruby
|
95
|
+
my_mocked_object = mock()
|
96
|
+
my_mocked_object.expects(:hello)
|
97
|
+
~~~
|
98
|
+
|
99
|
+
### Pure mock objects
|
100
|
+
|
101
|
+
If you wish to use objects for the sole purpose of being a mock, you can do so
|
102
|
+
by creating an empty object:
|
103
|
+
|
104
|
+
~~~ ruby
|
105
|
+
mock(my_mock_object = Object.new).hello
|
106
|
+
~~~
|
107
|
+
|
108
|
+
However as a shortcut you can also use #mock!:
|
109
|
+
|
110
|
+
~~~ ruby
|
111
|
+
# Create a new mock object with an empty #hello method, then retrieve that mock
|
112
|
+
# object via the #subject method
|
113
|
+
my_mock_object = mock!.hello.subject
|
114
|
+
~~~
|
115
|
+
|
116
|
+
### No #should_receive or #expects method
|
117
|
+
|
118
|
+
RR uses #method_missing to set your method expectation. This means you do not
|
119
|
+
need to use a method such as #should_receive or #expects.
|
120
|
+
|
121
|
+
~~~ ruby
|
122
|
+
# In Mocha, #expects sets the #hello method expectation:
|
123
|
+
my_object.expects(:hello)
|
124
|
+
# Using rspec-mocks, #should_receive sets the #hello method expectation:
|
125
|
+
my_object.should_receive(:hello)
|
126
|
+
# And here's how you say it using RR:
|
127
|
+
mock(my_object).hello
|
128
|
+
~~~
|
129
|
+
|
130
|
+
### #with method call is not necessary
|
131
|
+
|
132
|
+
The fact that RR uses #method_missing also makes using the #with method
|
133
|
+
unnecessary in most circumstances to set the argument expectation itself
|
134
|
+
(although you can still use it if you want):
|
135
|
+
|
136
|
+
~~~ ruby
|
137
|
+
# Mocha
|
138
|
+
my_object.expects(:hello).with('bob', 'jane')
|
139
|
+
# rspec-mocks
|
140
|
+
my_object.should_receive(:hello).with('bob', 'jane')
|
141
|
+
# RR
|
142
|
+
mock(my_object).hello('bob', 'jane')
|
143
|
+
mock(my_object).hello.with('bob', 'jane') # same thing, just more verbose
|
144
|
+
~~~
|
145
|
+
|
146
|
+
### Using a block to set the return value
|
147
|
+
|
148
|
+
RR supports using a block to set the return value as opposed to a specific
|
149
|
+
method call (although again, you can use #returns if you like):
|
150
|
+
|
151
|
+
~~~ ruby
|
152
|
+
# Mocha
|
153
|
+
my_object.expects(:hello).with('bob', 'jane').returns('Hello Bob and Jane')
|
154
|
+
# rspec-mocks
|
155
|
+
my_object.should_receive(:hello).with('bob', 'jane') { 'Hello Bob and Jane' }
|
156
|
+
my_object.should_receive(:hello).with('bob', 'jane').and_return('Hello Bob and Jane') # same thing, just more verbose
|
157
|
+
# RR
|
158
|
+
mock(my_object).hello('bob', 'jane') { 'Hello Bob and Jane' }
|
159
|
+
mock(my_object).hello('bob', 'jane').returns('Hello Bob and Jane') # same thing, just more verbose
|
160
|
+
~~~
|
161
|
+
|
162
|
+
|
163
|
+
## Using RR
|
164
|
+
|
165
|
+
To create a double on an object, you can use the following methods:
|
166
|
+
|
167
|
+
* #mock / #mock!
|
168
|
+
* #stub / #stub!
|
169
|
+
* #dont_allow / #dont_allow!
|
170
|
+
* #proxy / #proxy!
|
171
|
+
* #instance_of / #instance_of!
|
172
|
+
|
173
|
+
These methods are composable. #mock, #stub, and #dont_allow can be used by
|
174
|
+
themselves and are mutually exclusive. #proxy and #instance_of must be chained
|
175
|
+
with #mock or #stub. You can also chain #proxy and #instance_of together.
|
176
|
+
|
177
|
+
The ! (bang) version of these methods causes the subject object of the Double to
|
178
|
+
be instantiated.
|
179
|
+
|
180
|
+
### #mock
|
181
|
+
|
182
|
+
\#mock replaces the method on the object with an expectation and implementation.
|
183
|
+
The expectations are a mock will be called with certain arguments a certain
|
184
|
+
number of times (the default is once). You can also set the return value of the
|
185
|
+
method invocation.
|
186
|
+
|
187
|
+
*Learn more: <http://xunitpatterns.com/Mock%20Object.html>*
|
188
|
+
|
189
|
+
The following example sets an expectation that the view will receive a method
|
190
|
+
call to #render with the arguments `{:partial => "user_info"}` once. When the
|
191
|
+
method is called, `"Information"` is returned.
|
192
|
+
|
193
|
+
~~~ ruby
|
194
|
+
view = controller.template
|
195
|
+
mock(view).render(:partial => "user_info") {"Information"}
|
196
|
+
~~~
|
197
|
+
|
198
|
+
You can also allow any number of arguments to be passed into the mock like
|
199
|
+
this:
|
200
|
+
|
201
|
+
~~~ ruby
|
202
|
+
mock(view).render.with_any_args.twice do |*args|
|
203
|
+
if args.first == {:partial => "user_info"}
|
204
|
+
"User Info"
|
205
|
+
else
|
206
|
+
"Stuff in the view #{args.inspect}"
|
207
|
+
end
|
208
|
+
end
|
209
|
+
~~~
|
210
|
+
|
211
|
+
### #stub
|
212
|
+
|
213
|
+
\#stub replaces the method on the object with only an implementation. You can
|
214
|
+
still use arguments to differentiate which stub gets invoked.
|
215
|
+
|
216
|
+
*Learn more: <http://xunitpatterns.com/Test%20Stub.html>*
|
217
|
+
|
218
|
+
The following example makes the User.find method return `jane` when passed "42"
|
219
|
+
and returns `bob` when passed "99". If another id is passed to User.find, an
|
220
|
+
exception is raised.
|
221
|
+
|
222
|
+
~~~ ruby
|
223
|
+
jane = User.new
|
224
|
+
bob = User.new
|
225
|
+
stub(User).find('42') {jane}
|
226
|
+
stub(User).find('99') {bob}
|
227
|
+
stub(User).find do |id|
|
228
|
+
raise "Unexpected id #{id.inspect} passed to me"
|
229
|
+
end
|
230
|
+
~~~
|
231
|
+
|
232
|
+
### #dont_allow (aliased to #do_not_allow, #dont_call, and #do_not_call)
|
233
|
+
|
234
|
+
\#dont_allow is the opposite of #mock -- it sets an expectation on the Double
|
235
|
+
that it will never be called. If the Double actually does end up being called, a
|
236
|
+
TimesCalledError is raised.
|
237
|
+
|
238
|
+
~~~ ruby
|
239
|
+
dont_allow(User).find('42')
|
240
|
+
User.find('42') # raises a TimesCalledError
|
241
|
+
~~~
|
242
|
+
|
243
|
+
### `mock.proxy`
|
244
|
+
|
245
|
+
`mock.proxy` replaces the method on the object with an expectation,
|
246
|
+
implementation, and also invokes the actual method. `mock.proxy` also intercepts
|
247
|
+
the return value and passes it into the return value block.
|
248
|
+
|
249
|
+
The following example makes sets an expectation that `view.render({:partial =>
|
250
|
+
"right_navigation"})` gets called once and returns the actual content of the
|
251
|
+
rendered partial template. A call to `view.render({:partial => "user_info"})`
|
252
|
+
will render the "user_info" partial template and send the content into the block
|
253
|
+
and is represented by the `html` variable. An assertion is done on the value of
|
254
|
+
`html` and `"Different html"` is returned.
|
255
|
+
|
256
|
+
~~~ ruby
|
257
|
+
view = controller.template
|
258
|
+
mock.proxy(view).render(:partial => "right_navigation")
|
259
|
+
mock.proxy(view).render(:partial => "user_info") do |html|
|
260
|
+
html.should include("John Doe")
|
261
|
+
"Different html"
|
262
|
+
end
|
263
|
+
~~~
|
264
|
+
|
265
|
+
You can also use `mock.proxy` to set expectations on the returned value. In the
|
266
|
+
following example, a call to User.find('5') does the normal ActiveRecord
|
267
|
+
implementation and passes the actual value, represented by the variable `bob`,
|
268
|
+
into the block. `bob` is then set with a `mock.proxy` for projects to return only
|
269
|
+
the first 3 projects. `bob` is also mocked so that #valid? returns false.
|
270
|
+
|
271
|
+
~~~ ruby
|
272
|
+
mock.proxy(User).find('5') do |bob|
|
273
|
+
mock.proxy(bob).projects do |projects|
|
274
|
+
projects[0..3]
|
275
|
+
end
|
276
|
+
mock(bob).valid? { false }
|
277
|
+
bob
|
278
|
+
end
|
279
|
+
~~~
|
280
|
+
|
281
|
+
### `stub.proxy`
|
282
|
+
|
283
|
+
Intercept the return value of a method call. The following example verifies
|
284
|
+
`render(:partial)` will be called and renders the partial.
|
285
|
+
|
286
|
+
~~~ ruby
|
287
|
+
view = controller.template
|
288
|
+
stub.proxy(view).render(:partial => "user_info") do |html|
|
289
|
+
html.should include("Joe Smith")
|
290
|
+
html
|
291
|
+
end
|
292
|
+
~~~
|
293
|
+
|
294
|
+
### #any_instance_of
|
295
|
+
|
296
|
+
Allows stubs to be added to all instances of a class. It works by binding to
|
297
|
+
methods from the class itself, rather than the eigenclass. This allows all
|
298
|
+
instances (excluding instances with the method redefined in the eigenclass) to
|
299
|
+
get the change.
|
300
|
+
|
301
|
+
Due to Ruby runtime limitations, mocks will not work as expected. It's not
|
302
|
+
obviously feasible (without an ObjectSpace lookup) to support all of RR's
|
303
|
+
methods (such as mocking). ObjectSpace is not readily supported in JRuby, since
|
304
|
+
it causes general slowness in the interpreter. I'm of the opinion that test
|
305
|
+
speed is more important than having mocks on all instances of a class. If there
|
306
|
+
is another solution, I'd be willing to add it.
|
307
|
+
|
308
|
+
~~~ ruby
|
309
|
+
any_instance_of(User) do |u|
|
310
|
+
stub(u).valid? { false }
|
311
|
+
end
|
312
|
+
# or
|
313
|
+
any_instance_of(User, :valid? => false)
|
314
|
+
# or
|
315
|
+
any_instance_of(User, :valid? => lambda { false })
|
316
|
+
~~~
|
317
|
+
|
318
|
+
### Spies
|
319
|
+
|
320
|
+
Adding a DoubleInjection to an object + method (done by #stub, #mock, or
|
321
|
+
\#dont_allow) causes RR to record any method invocations to the object + method.
|
322
|
+
Assertions can then be made on the recorded method calls.
|
323
|
+
|
324
|
+
#### Test::Unit
|
325
|
+
|
326
|
+
~~~ ruby
|
327
|
+
subject = Object.new
|
328
|
+
stub(subject).foo
|
329
|
+
subject.foo(1)
|
330
|
+
assert_received(subject) {|subject| subject.foo(1) }
|
331
|
+
assert_received(subject) {|subject| subject.bar } # This fails
|
332
|
+
~~~
|
333
|
+
|
334
|
+
#### RSpec
|
335
|
+
|
336
|
+
~~~ ruby
|
337
|
+
subject = Object.new
|
338
|
+
stub(subject).foo
|
339
|
+
subject.foo(1)
|
340
|
+
subject.should have_received.foo(1)
|
341
|
+
subject.should have_received.bar # This fails
|
342
|
+
~~~
|
343
|
+
|
344
|
+
### Block syntax
|
345
|
+
|
346
|
+
The block syntax has two modes:
|
347
|
+
|
348
|
+
* A normal block mode with a DoubleDefinitionCreatorProxy argument:
|
349
|
+
|
350
|
+
~~~ ruby
|
351
|
+
script = MyScript.new
|
352
|
+
mock(script) do |expect|
|
353
|
+
expect.system("cd #{RAILS_ENV}") {true}
|
354
|
+
expect.system("rake foo:bar") {true}
|
355
|
+
expect.system("rake baz") {true}
|
356
|
+
end
|
357
|
+
~~~
|
358
|
+
|
359
|
+
* An instance_eval mode where the DoubleDefinitionCreatorProxy is
|
360
|
+
instance_eval'ed:
|
361
|
+
|
362
|
+
~~~ ruby
|
363
|
+
script = MyScript.new
|
364
|
+
mock(script) do
|
365
|
+
system("cd #{RAILS_ENV}") {true}
|
366
|
+
system("rake foo:bar") {true}
|
367
|
+
system("rake baz") {true}
|
368
|
+
end
|
369
|
+
~~~
|
370
|
+
|
371
|
+
### Double graphs
|
372
|
+
|
373
|
+
RR has a method-chaining API support for double graphs. For example, let's say
|
374
|
+
you want an object to receive a method call to #foo, and have the return value
|
375
|
+
receive a method call to #bar.
|
376
|
+
|
377
|
+
In RR, you would do:
|
378
|
+
|
379
|
+
~~~ ruby
|
380
|
+
stub(object).foo.stub!.bar { :baz }
|
381
|
+
object.foo.bar #=> :baz
|
382
|
+
# or:
|
383
|
+
stub(object).foo { stub!.bar {:baz} }
|
384
|
+
object.foo.bar #=> :baz
|
385
|
+
# or:
|
386
|
+
bar = stub!.bar { :baz }
|
387
|
+
stub(object).foo { bar }
|
388
|
+
object.foo.bar #=> :baz
|
389
|
+
~~~
|
390
|
+
|
391
|
+
### Modifying doubles
|
392
|
+
|
393
|
+
Whenever you create a double by calling a method on an object you've wrapped,
|
394
|
+
you get back a special object: a DoubleDefinition. In other words:
|
395
|
+
|
396
|
+
~~~ ruby
|
397
|
+
stub(object).foo #=> RR::DoubleDefinitions::DoubleDefinition
|
398
|
+
~~~
|
399
|
+
|
400
|
+
There are several ways you can modify the behavior of these doubles via the
|
401
|
+
DoubleDefinition API, and they are listed in this section.
|
402
|
+
|
403
|
+
Quick note: all of these methods accept blocks as a shortcut for setting the
|
404
|
+
return value at the same time. In other words, if you have something like this:
|
405
|
+
|
406
|
+
~~~ ruby
|
407
|
+
mock(object).foo { 'bar' }
|
408
|
+
~~~
|
409
|
+
|
410
|
+
you can modify the mock and keep the return value like so:
|
411
|
+
|
412
|
+
~~~ ruby
|
413
|
+
mock(object).foo.times(2) { 'bar' }
|
414
|
+
~~~
|
415
|
+
|
416
|
+
You can even flip around the block:
|
417
|
+
|
418
|
+
~~~ ruby
|
419
|
+
mock(object).foo { 'bar' }.times(2)
|
420
|
+
~~~
|
421
|
+
|
422
|
+
And as we explain below, this is just a shortcut for:
|
423
|
+
|
424
|
+
~~~ ruby
|
425
|
+
mock(object).foo.returns { 'bar' }.times(2)
|
426
|
+
~~~
|
427
|
+
|
428
|
+
#### Stubbing method implementation / return value
|
429
|
+
|
430
|
+
There are two ways here. We have already covered this usage:
|
431
|
+
|
432
|
+
~~~ ruby
|
433
|
+
stub(object).foo { 'bar' }
|
434
|
+
~~~
|
435
|
+
|
436
|
+
However, you can also use #returns if it's more clear to you:
|
437
|
+
|
438
|
+
~~~ ruby
|
439
|
+
stub(object).foo.returns { 'bar' }
|
440
|
+
~~~
|
441
|
+
|
442
|
+
Regardless, keep in mind that you're actually supplying the implementation of
|
443
|
+
the method in question here, so you can put whatever you want in this block:
|
444
|
+
|
445
|
+
~~~ ruby
|
446
|
+
stub(object).foo { |age, count|
|
447
|
+
raise 'hell' if age < 16
|
448
|
+
ret = yield count
|
449
|
+
blue? ? ret : 'whatever'
|
450
|
+
}
|
451
|
+
~~~
|
452
|
+
|
453
|
+
This works for mocks as well as stubs.
|
454
|
+
|
455
|
+
#### Stubbing method implementation based on argument expectation
|
456
|
+
|
457
|
+
A double's implementation is always tied to its argument expectation. This means
|
458
|
+
that it is possible to return one value if the method is called one way and
|
459
|
+
return a second value if the method is called a second way. For example:
|
460
|
+
|
461
|
+
~~~ ruby
|
462
|
+
stub(object).foo { 'bar' }
|
463
|
+
stub(object).foo(1, 2) { 'baz' }
|
464
|
+
object.foo #=> 'bar'
|
465
|
+
object.foo(1, 2) #=> 'baz'
|
466
|
+
~~~
|
467
|
+
|
468
|
+
This works for mocks as well as stubs.
|
469
|
+
|
470
|
+
#### Stubbing method to yield given block
|
471
|
+
|
472
|
+
If you need to stub a method such that a block given to it is guaranteed to be
|
473
|
+
called when the method is called, then use #yields.
|
474
|
+
|
475
|
+
~~~ ruby
|
476
|
+
# This outputs: [1, 2, 3]
|
477
|
+
stub(object).foo.yields(1, 2, 3)
|
478
|
+
object.foo {|*args| pp args }
|
479
|
+
~~~
|
480
|
+
|
481
|
+
This works for mocks as well as stubs.
|
482
|
+
|
483
|
+
#### Expecting method to be called with exact argument list
|
484
|
+
|
485
|
+
There are two ways to do this. Here is the way we have shown before:
|
486
|
+
|
487
|
+
~~~ ruby
|
488
|
+
mock(object).foo(1, 2)
|
489
|
+
object.foo(1, 2) # ok
|
490
|
+
object.foo(3) # fails
|
491
|
+
~~~
|
492
|
+
|
493
|
+
But if this is not clear enough to you, you can use #with:
|
494
|
+
|
495
|
+
~~~ ruby
|
496
|
+
mock(object).foo.with(1, 2)
|
497
|
+
object.foo(1, 2) # ok
|
498
|
+
object.foo(3) # fails
|
499
|
+
~~~
|
500
|
+
|
501
|
+
As seen above, if you create an the expectation for a set of arguments and the
|
502
|
+
method is called with another set of arguments, even if *those* arguments are of
|
503
|
+
a completely different size, you will need to create another expectation for
|
504
|
+
them somehow. A simple way to do this is to #stub the method beforehand:
|
505
|
+
|
506
|
+
~~~ ruby
|
507
|
+
stub(object).foo
|
508
|
+
mock(object).foo(1, 2)
|
509
|
+
object.foo(1, 2) # ok
|
510
|
+
object.foo(3) # ok too
|
511
|
+
~~~
|
512
|
+
|
513
|
+
#### Expecting method to be called with any arguments
|
514
|
+
|
515
|
+
Use #with_any_args:
|
516
|
+
|
517
|
+
~~~ ruby
|
518
|
+
mock(object).foo.with_any_args
|
519
|
+
object.foo # ok
|
520
|
+
object.foo(1) # also ok
|
521
|
+
object.foo(1, 2) # also ok
|
522
|
+
# ... you get the idea
|
523
|
+
~~~
|
524
|
+
|
525
|
+
#### Expecting method to be called with no arguments
|
526
|
+
|
527
|
+
Use #with_no_args:
|
528
|
+
|
529
|
+
~~~ ruby
|
530
|
+
mock(object).foo.with_no_args
|
531
|
+
object.foo # ok
|
532
|
+
object.foo(1) # fails
|
533
|
+
~~~
|
534
|
+
|
535
|
+
#### Expecting method to never be called
|
536
|
+
|
537
|
+
Use #never:
|
538
|
+
|
539
|
+
~~~ ruby
|
540
|
+
mock(object).foo.never
|
541
|
+
object.foo # fails
|
542
|
+
~~~
|
543
|
+
|
544
|
+
You can also narrow the negative expectation to a specific set of arguments.
|
545
|
+
Of course, you will still need to set explicit expectations for any other ways
|
546
|
+
that your method could be called. For instance:
|
547
|
+
|
548
|
+
~~~ ruby
|
549
|
+
mock(object).foo.with(1, 2).never
|
550
|
+
object.foo(3, 4) # fails
|
551
|
+
~~~
|
552
|
+
|
553
|
+
RR will complain here that this is an unexpected invocation, so we need to add
|
554
|
+
an expectation for this beforehand. We can do this easily with #stub:
|
555
|
+
|
556
|
+
~~~ ruby
|
557
|
+
stub(object).foo
|
558
|
+
~~~
|
559
|
+
|
560
|
+
So, a full example would look like:
|
561
|
+
|
562
|
+
~~~ ruby
|
563
|
+
stub(object).foo
|
564
|
+
mock(object).foo.with(1, 2).never
|
565
|
+
object.foo(3, 4) # ok
|
566
|
+
object.foo(1, 2) # fails
|
567
|
+
~~~
|
568
|
+
|
569
|
+
Alternatively, you can also use #dont_allow, although the same rules apply as
|
570
|
+
above:
|
571
|
+
|
572
|
+
~~~ ruby
|
573
|
+
stub(object).foo
|
574
|
+
dont_allow(object).foo.with(1, 2)
|
575
|
+
object.foo(3, 4) # ok
|
576
|
+
object.foo(1, 2) # fails
|
577
|
+
~~~
|
578
|
+
|
579
|
+
#### Expecting method to be called only once
|
580
|
+
|
581
|
+
Use #once:
|
582
|
+
|
583
|
+
~~~ ruby
|
584
|
+
mock(object).foo.once
|
585
|
+
object.foo
|
586
|
+
object.foo # fails
|
587
|
+
~~~
|
588
|
+
|
589
|
+
#### Expecting method to called exact number of times
|
590
|
+
|
591
|
+
Use #times:
|
592
|
+
|
593
|
+
~~~ ruby
|
594
|
+
mock(object).foo.times(3)
|
595
|
+
object.foo
|
596
|
+
object.foo
|
597
|
+
object.foo
|
598
|
+
object.foo # fails
|
599
|
+
~~~
|
600
|
+
|
601
|
+
#### Expecting method to be called minimum number of times
|
602
|
+
|
603
|
+
Use #at_least.
|
604
|
+
|
605
|
+
For instance, this would pass:
|
606
|
+
|
607
|
+
~~~ ruby
|
608
|
+
mock(object).foo.at_least(3)
|
609
|
+
object.foo
|
610
|
+
object.foo
|
611
|
+
object.foo
|
612
|
+
object.foo
|
613
|
+
~~~
|
614
|
+
|
615
|
+
But this would fail:
|
616
|
+
|
617
|
+
~~~ ruby
|
618
|
+
mock(object).foo.at_least(3)
|
619
|
+
object.foo
|
620
|
+
object.foo
|
621
|
+
~~~
|
622
|
+
|
623
|
+
#### Expecting method to be called maximum number of times
|
624
|
+
|
625
|
+
Use #at_most.
|
626
|
+
|
627
|
+
For instance, this would pass:
|
628
|
+
|
629
|
+
~~~ ruby
|
630
|
+
mock(object).foo.at_most(3)
|
631
|
+
object.foo
|
632
|
+
object.foo
|
633
|
+
~~~
|
634
|
+
|
635
|
+
But this would fail:
|
636
|
+
|
637
|
+
~~~ ruby
|
638
|
+
mock(object).foo.at_most(3)
|
639
|
+
object.foo
|
640
|
+
object.foo
|
641
|
+
object.foo
|
642
|
+
object.foo
|
643
|
+
~~~
|
644
|
+
|
645
|
+
#### Expecting method to be called any number of times
|
646
|
+
|
647
|
+
Use #any_times. This effectively disables the times-called expectation.
|
648
|
+
|
649
|
+
~~~ ruby
|
650
|
+
mock(object).foo.any_times
|
651
|
+
object.foo
|
652
|
+
object.foo
|
653
|
+
object.foo
|
654
|
+
...
|
655
|
+
~~~
|
656
|
+
|
657
|
+
You can also use #times + the argument invocation #any_times matcher:
|
658
|
+
|
659
|
+
~~~ ruby
|
660
|
+
mock(object).foo.times(any_times)
|
661
|
+
object.foo
|
662
|
+
object.foo
|
663
|
+
object.foo
|
664
|
+
...
|
665
|
+
~~~
|
666
|
+
|
667
|
+
|
668
|
+
|
669
|
+
### Argument wildcard matchers
|
670
|
+
|
671
|
+
RR also has several methods which you can use with argument expectations which
|
672
|
+
act as placeholders for arguments. When RR goes to verify the argument
|
673
|
+
expectation it will compare the placeholders with the actual arguments the
|
674
|
+
method was called with, and if they match then the test passes (hence
|
675
|
+
"matchers").
|
676
|
+
|
677
|
+
#### #anything
|
678
|
+
|
679
|
+
Matches any value.
|
680
|
+
|
681
|
+
~~~ ruby
|
682
|
+
mock(object).foobar(1, anything)
|
683
|
+
object.foobar(1, :my_symbol)
|
684
|
+
~~~
|
685
|
+
|
686
|
+
#### #is_a
|
687
|
+
|
688
|
+
Matches an object which `.is_a?(*Class*)`.
|
689
|
+
|
690
|
+
~~~ ruby
|
691
|
+
mock(object).foobar(is_a(Time))
|
692
|
+
object.foobar(Time.now)
|
693
|
+
~~~
|
694
|
+
|
695
|
+
#### #numeric
|
696
|
+
|
697
|
+
Matches a value which `.is_a?(Numeric)`.
|
698
|
+
|
699
|
+
~~~ ruby
|
700
|
+
mock(object).foobar(numeric)
|
701
|
+
object.foobar(99)
|
702
|
+
~~~~
|
703
|
+
|
704
|
+
#### #boolean
|
705
|
+
|
706
|
+
Matches true or false.
|
707
|
+
|
708
|
+
~~~ ruby
|
709
|
+
mock(object).foobar(boolean)
|
710
|
+
object.foobar(false)
|
711
|
+
~~~
|
712
|
+
|
713
|
+
#### #duck_type
|
714
|
+
|
715
|
+
Matches an object which responds to certain methods.
|
716
|
+
|
717
|
+
~~~ ruby
|
718
|
+
mock(object).foobar(duck_type(:walk, :talk))
|
719
|
+
arg = Object.new
|
720
|
+
def arg.walk; 'waddle'; end
|
721
|
+
def arg.talk; 'quack'; end
|
722
|
+
object.foobar(arg)
|
723
|
+
~~~
|
724
|
+
|
725
|
+
#### Ranges
|
726
|
+
|
727
|
+
Matches a number within a certain range.
|
728
|
+
|
729
|
+
~~~ ruby
|
730
|
+
mock(object).foobar(1..10)
|
731
|
+
object.foobar(5)
|
732
|
+
~~~
|
733
|
+
|
734
|
+
#### Regexps
|
735
|
+
|
736
|
+
Matches a string which matches a certain regex.
|
737
|
+
|
738
|
+
~~~ ruby
|
739
|
+
mock(object).foobar(/on/)
|
740
|
+
object.foobar("ruby on rails")
|
741
|
+
~~~
|
742
|
+
|
743
|
+
#### #hash_including
|
744
|
+
|
745
|
+
Matches a hash which contains a subset of keys and values.
|
746
|
+
|
747
|
+
~~~ ruby
|
748
|
+
mock(object).foobar(hash_including(:red => "#FF0000", :blue => "#0000FF"))
|
749
|
+
object.foobar({:red => "#FF0000", :blue => "#0000FF", :green => "#00FF00"})
|
750
|
+
~~~
|
751
|
+
|
752
|
+
#### #satisfy
|
753
|
+
|
754
|
+
Matches an argument which satisfies a custom requirement.
|
755
|
+
|
756
|
+
~~~ ruby
|
757
|
+
mock(object).foobar(satisfy {|arg| arg.length == 2 })
|
758
|
+
object.foobar("xy")
|
759
|
+
~~~
|
760
|
+
|
761
|
+
#### Writing your own argument matchers
|
762
|
+
|
763
|
+
Writing a custom argument wildcard matcher is not difficult. See
|
764
|
+
RR::WildcardMatchers for details.
|
765
|
+
|
766
|
+
### Invocation amount wildcard matchers
|
767
|
+
|
768
|
+
#### #any_times
|
769
|
+
|
770
|
+
Only used with #times and matches any number.
|
771
|
+
|
772
|
+
~~~ ruby
|
773
|
+
mock(object).foo.times(any_times) { return_value }
|
774
|
+
object.foo
|
775
|
+
object.foo
|
776
|
+
object.foo
|
777
|
+
...
|
778
|
+
~~~
|
779
|
+
|
780
|
+
|
781
|
+
## Special thanks to
|
782
|
+
|
783
|
+
With any development effort, there are countless people who have contributed to
|
784
|
+
making it possible. We all are standing on the shoulders of giants. If you have
|
785
|
+
directly contributed to RR and I missed you in this list, please let me know and
|
786
|
+
I will add you. Thanks!
|
787
|
+
|
788
|
+
* Andreas Haller for patches
|
789
|
+
* Aslak Hellesoy for Developing RSpec
|
790
|
+
* Bryan Helmkamp for patches
|
791
|
+
* Caleb Spare for patches
|
792
|
+
* Christopher Redinger for patches
|
793
|
+
* Dan North for syntax ideas
|
794
|
+
* Dave Astels for some BDD inspiration
|
795
|
+
* Dave Myron for a bug report
|
796
|
+
* David Chelimsky for encouragement to make the RR framework, for developing the
|
797
|
+
RSpec mock framework, syntax ideas, and patches
|
798
|
+
* Daniel Sudol for identifing performance issues with RR
|
799
|
+
* Dmitry Ratnikov for patches
|
800
|
+
* Eugene Pimenov for patches
|
801
|
+
* Evan Phoenix for patches
|
802
|
+
* Felix Morio for pairing with me
|
803
|
+
* Gabriel Horner for patches
|
804
|
+
* Gavin Miller for patches
|
805
|
+
* Gerard Meszaros for his excellent book "xUnit Test Patterns"
|
806
|
+
* James Mead for developing Mocha
|
807
|
+
* Jeff Whitmire for documentation suggestions
|
808
|
+
* Jim Weirich for developing Flexmock, the first Terse ruby mock framework in Ruby
|
809
|
+
* Joe Ferris for patches
|
810
|
+
* Matthew O'Connor for patches and pairing with me
|
811
|
+
* Michael Niessner for patches and pairing with me
|
812
|
+
* Mike Mangino (from Elevated Rails) for patches and pairing with me
|
813
|
+
* Myron Marston for bug reports
|
814
|
+
* Nick Kallen for documentation suggestions, bug reports, and patches
|
815
|
+
* Nathan Sobo for various ideas and inspiration for cleaner and more expressive code
|
816
|
+
* Parker Thompson for pairing with me
|
817
|
+
* Phil Darnowsky for patches
|
818
|
+
* Pivotal Labs for sponsoring RR development
|
819
|
+
* Steven Baker for Developing RSpec
|
820
|
+
* Tatsuya Ono for patches
|
821
|
+
* Tuomas Kareinen for a bug report
|
822
|
+
|