flexmock 0.5.1 → 0.6.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.
- data/CHANGELOG +10 -1
- data/README +390 -209
- data/Rakefile +31 -10
- data/doc/GoogleExample.rdoc +275 -0
- data/doc/releases/flexmock-0.6.0.rdoc +136 -0
- data/lib/flexmock.rb +3 -1160
- data/lib/flexmock/argument_matchers.rb +57 -0
- data/lib/flexmock/argument_types.rb +42 -0
- data/lib/flexmock/base.rb +22 -0
- data/lib/flexmock/composite.rb +10 -0
- data/lib/flexmock/core.rb +206 -0
- data/lib/flexmock/core_class_methods.rb +92 -0
- data/lib/flexmock/default_framework_adapter.rb +31 -0
- data/lib/flexmock/expectation.rb +334 -0
- data/lib/flexmock/expectation_director.rb +59 -0
- data/lib/flexmock/mock_container.rb +159 -0
- data/lib/flexmock/noop.rb +13 -0
- data/lib/flexmock/partial_mock.rb +226 -0
- data/lib/flexmock/recorder.rb +71 -0
- data/lib/flexmock/rspec.rb +34 -0
- data/lib/flexmock/test_unit.rb +32 -0
- data/lib/flexmock/test_unit_integration.rb +53 -0
- data/lib/flexmock/validators.rb +77 -0
- data/test/rspec_integration/integration_spec.rb +36 -0
- data/test/test_container_methods.rb +119 -0
- data/test/test_default_framework_adapter.rb +39 -0
- data/test/test_example.rb +1 -1
- data/test/test_extended_should_receive.rb +63 -0
- data/test/test_mock.rb +1 -1
- data/test/test_naming.rb +1 -1
- data/test/{test_any_instance.rb → test_new_instances.rb} +15 -8
- data/test/{test_stubbing.rb → test_partial_mock.rb} +44 -44
- data/test/test_record_mode.rb +1 -1
- data/test/test_samples.rb +6 -8
- data/test/test_should_receive.rb +7 -3
- data/test/test_tu_integration.rb +1 -1
- data/test/test_unit_integration/test_auto_test_unit.rb +34 -0
- metadata +30 -5
- data/test/test_class_interception.rb +0 -140
data/CHANGELOG
CHANGED
@@ -2,7 +2,16 @@
|
|
2
2
|
|
3
3
|
= Changes for FlexMock
|
4
4
|
|
5
|
-
==
|
5
|
+
== Version 0.6.0
|
6
|
+
|
7
|
+
* Dropped class interception.
|
8
|
+
* Refactored into more granular classes.
|
9
|
+
* Added RSpec integration.
|
10
|
+
* Added hash expectations to flexmock() and should_expect().
|
11
|
+
* Integrated partial mocks into the flexmock() methods.
|
12
|
+
* Allow non-block configuration of new_instances.
|
13
|
+
|
14
|
+
== Version 0.5.1
|
6
15
|
|
7
16
|
* Changed the name of any_instance to new_instances.
|
8
17
|
Deprecated any_instance.
|
data/README
CHANGED
@@ -3,13 +3,13 @@
|
|
3
3
|
FlexMock is a simple, but flexible, mock object library for Ruby unit
|
4
4
|
testing.
|
5
5
|
|
6
|
-
Version :: 0.
|
6
|
+
Version :: 0.6.0
|
7
7
|
|
8
8
|
= Links
|
9
9
|
|
10
|
-
<b>Documents</b> :: http://
|
10
|
+
<b>Documents</b> :: http://flexmock.rubyforge.org
|
11
11
|
<b>RubyGems</b> :: Install with: <b>gem install flexmock</b>
|
12
|
-
<b>Download</b> :: Download from RubyForge at http://rubyforge.org/frs/?group_id=170
|
12
|
+
<b>Download</b> :: Download from RubyForge at http://rubyforge.org/frs/?group_id=3433 (pre 0.6.0 versions may be found at http://rubyforge.org/frs/?group_id=170)
|
13
13
|
|
14
14
|
== Installation
|
15
15
|
|
@@ -27,7 +27,7 @@ mock object that responds to the +read_temperature+ message.
|
|
27
27
|
Here's the complete example:
|
28
28
|
|
29
29
|
require 'test/unit'
|
30
|
-
require 'flexmock'
|
30
|
+
require 'flexmock/test_unit'
|
31
31
|
|
32
32
|
class TemperatureSampler
|
33
33
|
def initialize(sensor)
|
@@ -35,149 +35,299 @@ Here's the complete example:
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def average_temp
|
38
|
-
total = (0...3).collect {
|
38
|
+
total = (0...3).collect {
|
39
|
+
@sensor.read_temperature
|
40
|
+
}.inject { |i, s| i + s }
|
39
41
|
total / 3.0
|
40
42
|
end
|
41
43
|
end
|
42
44
|
|
43
45
|
class TestTemperatureSampler < Test::Unit::TestCase
|
44
|
-
|
45
|
-
|
46
|
-
def test_temperature_sampler
|
46
|
+
def test_sensor_can_average_three_temperature_readings
|
47
47
|
sensor = flexmock("temp")
|
48
|
-
sensor.should_receive(:read_temperature).times(3).
|
48
|
+
sensor.should_receive(:read_temperature).times(3).
|
49
|
+
and_return(10, 12, 14)
|
49
50
|
|
50
51
|
sampler = TemperatureSampler.new(sensor)
|
51
52
|
assert_equal 12, sampler.average_temp
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
You can find an extended example of FlexMock in {Google Example}[http://flexmock.rubyforge.org/files/doc/GoogleExample_rdoc.html].
|
57
|
+
|
58
|
+
== Test::Unit Integration
|
59
|
+
|
60
|
+
FlexMock integrates nicely with Test::Unit. Just require the
|
61
|
+
'flexmock/test_unit' file at the top of your test file. The +flexmock+ method
|
62
|
+
will be available for mock creation, and any created mocks will be
|
63
|
+
automatically validated and closed at the end of the individual test.
|
64
|
+
|
65
|
+
Your test case will look something like this:
|
52
66
|
|
53
|
-
|
54
|
-
|
55
|
-
|
67
|
+
require 'flexmock/test_unit'
|
68
|
+
|
69
|
+
class TestDog < Test::Case::TestCase
|
70
|
+
def test_dog_wags
|
71
|
+
tail_mock = flexmock(:wag => :happy)
|
72
|
+
assert_equal :happy, tail_mock.wag
|
56
73
|
end
|
57
74
|
end
|
58
75
|
|
76
|
+
<b>NOTE:</b> If you don't want to automatically extend every TestCase with the
|
77
|
+
flexmock methods and overhead, then require the 'flexmock' file and explicitly
|
78
|
+
include the FlexMock::TestCase module in each test case class where you wish
|
79
|
+
to use mock objects. FlexMock versions prior to 0.6.0 required the explicit
|
80
|
+
include.
|
81
|
+
|
82
|
+
== RSpec Integration
|
83
|
+
|
84
|
+
FlexMock also supports integration with the RSpec behavior specification framework. Starting with version 0.9.0 of RSpec, you will be able to say:
|
85
|
+
|
86
|
+
Spec::Runner.configure do |config|
|
87
|
+
config.mock_with :flexmock
|
88
|
+
end
|
89
|
+
|
90
|
+
context "Using FlexMock with RSpec" do
|
91
|
+
specify "should be able to create a mock" do
|
92
|
+
m = flexmock(:foo => :bar)
|
93
|
+
m.foo.should === :bar
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
If you wish to try this prior to the release of RSpec 0.9.0, check out the trunk of the RSpec subversion repository.
|
98
|
+
|
59
99
|
== Quick Reference
|
60
100
|
|
101
|
+
=== Creating Mock Objects
|
102
|
+
|
103
|
+
The +flexmock+ method is used to create mocks in various configurations. Here's a quick rundown of the most common options. See FlexMock::MockContainer#flexmock for more details.
|
104
|
+
|
105
|
+
* <b>m = flexmock("joe")</b>
|
106
|
+
|
107
|
+
Create a mock object named "joe" (the name is used in reporting errors).
|
108
|
+
|
109
|
+
* <b>m = flexmock(:foo => :bar, :baz => :froz)</b>
|
110
|
+
|
111
|
+
Create a mock object and define two mocked methods (:foo and :baz) that
|
112
|
+
return the values :bar and :froz respectively. This is useful when creating
|
113
|
+
mock objects with just a few methods and simple return values.
|
114
|
+
|
115
|
+
* <b>m = flexmock("joe", :foo => :bar, :bar => :froz)</b>
|
116
|
+
|
117
|
+
You can combine the mock name and an expectation hash in the same call to
|
118
|
+
flexmock.
|
119
|
+
|
120
|
+
* <b>m = flexmock(real_object)</b>
|
121
|
+
|
122
|
+
If you you give +flexmock+ a real object in the argument list, it will treat
|
123
|
+
that real object as a base for a partial mock object. The return value +m+
|
124
|
+
may be used to set expectations. The real_object should be used in the
|
125
|
+
reference portion of the test.
|
126
|
+
|
127
|
+
* <b>m = flexmock(real_object, "name", :foo => :baz)</b>
|
128
|
+
|
129
|
+
Names and expectation hashes may be used with partial mocks as well.
|
130
|
+
|
131
|
+
* <b>m = flexmock(:base, real_string_object)</b>
|
132
|
+
|
133
|
+
Since Strings (and Symbols for that matter) are used for mock names,
|
134
|
+
FlexMock will not recognize them as the base for a partial mock. To force a
|
135
|
+
string to be used as a partial mock base, proceed the string object in the
|
136
|
+
calling sequence with :base.
|
137
|
+
|
138
|
+
* <b>m = flexmock(...) { |mock| mock.should_receive(...) }</b>
|
139
|
+
|
140
|
+
If a block is given to any of the +flexmock+ forms, the mock object will be
|
141
|
+
passed to the block as an argument. Code in the block can set the desired
|
142
|
+
expectations for the mock object.
|
143
|
+
|
144
|
+
<b>NOTE:</b> Versions of FlexMock prior to 0.6.0 used +flexstub+ to create partial mocks. The +flexmock+ method now assumes all the functionality that was spread out between two different methods. +flexstub+ is still available for backward compatibility.
|
145
|
+
|
61
146
|
=== Expectation Declarators
|
62
147
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
may be chained to the +should_receive+ call.
|
71
|
-
|
72
|
-
* <b><tt>should_expect</tt></b> -- Creates a mock recording object
|
73
|
-
that will translate received method calls into mock expectations.
|
74
|
-
The recorder is passed to a block supplied with the +should_expect+
|
75
|
-
method. See examples below.
|
76
|
-
|
77
|
-
* <b><tt>with(<em>arglist</em>)</tt></b> -- Declares that this
|
78
|
-
expectation matches messages that match the given argument list.
|
79
|
-
The <tt>===</tt> operator is used on a argument by argument basis to
|
80
|
-
determine matching. This means that most literal values match
|
81
|
-
literally, class values match any instance of a class and regular
|
82
|
-
expression match any matching string (after a +to_s+ conversion).
|
83
|
-
See argument validators (below) for details on argument validation
|
84
|
-
options.
|
85
|
-
|
86
|
-
* <b><tt>with_any_args</tt></b> -- Declares that this expectation
|
87
|
-
matches the message with any argument (default)
|
88
|
-
|
89
|
-
* <b><tt>with_no_args</tt></b> -- Declares that this expectation
|
90
|
-
matches messages with no arguments
|
91
|
-
|
92
|
-
* <b><tt>and_return(<em>value, ...</em>)</tt></b> -- Declares
|
93
|
-
that the message will return the given value.
|
94
|
-
* If a single value is given, it will be returned for all matching calls.
|
95
|
-
* If multiple values are given, they will be returned in sequence
|
96
|
-
for each successive matching calls. The last value will be
|
97
|
-
repeatably returned if the number of matching calls exceeds the
|
98
|
-
number of values.
|
99
|
-
* If a block is given, its yielded value will be returned. (the
|
100
|
-
block will receive all the arguments given to the mocked method)
|
101
|
-
* The default return value is nil.
|
102
|
-
|
103
|
-
* <b><tt>returns(<em>value, ...</em>)</tt></b> -- Alias for
|
104
|
-
<tt>and_return</tt>.
|
105
|
-
|
106
|
-
* <b><tt>returns { |args| code ... }</tt></b> -- Declares that the
|
107
|
-
message will return whatever the block calculates. The actual
|
108
|
-
arguments in the message will be passed to the block.
|
109
|
-
|
110
|
-
* <b><tt>zero_or_more_times</tt></b> -- Declares that the message is
|
111
|
-
may be sent zero or more times (default, equivalent to
|
112
|
-
<tt>at_least.never</tt>).
|
113
|
-
|
114
|
-
* <b><tt>once</tt></b> -- Declares that the message is only sent once.
|
115
|
-
<tt>at_least</tt> / <tt>at_most</tt> modifiers are allowed.
|
148
|
+
Once a mock is created, you need to define what that mock should expect to
|
149
|
+
see. Expectation declarators are used to specify these expectations placed
|
150
|
+
upon received method calls. A basic expectation, created with the
|
151
|
+
+should_receive+ method, just establishes the fact that a method may (or may
|
152
|
+
not) be called on the mock object. Refinements to that expectation may be
|
153
|
+
additionally declared. FlexMock always starts with the most general
|
154
|
+
expectation and adds constraints to that.
|
116
155
|
|
117
|
-
|
118
|
-
twice. <tt>at_least</tt> / <tt>at_most</tt> modifiers are allowed.
|
156
|
+
For example, the following code:
|
119
157
|
|
120
|
-
|
121
|
-
|
158
|
+
mock.should_recieve(:average).and_return(12)
|
159
|
+
|
160
|
+
Means that the mock will now accept method calls to an +average+ method. The
|
161
|
+
expectation will accept any arguments and may be called any number of times
|
162
|
+
(including zero times). Strictly speaking, the +and_return+ part of the
|
163
|
+
declaration isn't exactly a constraint, but it does specify what value the
|
164
|
+
mock will return when the expectation is matched.
|
165
|
+
|
166
|
+
If you want to be more specific, you need to add additional constraints to
|
167
|
+
your expectation. Here are some examples:
|
168
|
+
|
169
|
+
mock.should_receive(:average).with(12).once
|
170
|
+
|
171
|
+
mock.should_receive(:average).with(Integer).
|
172
|
+
at_least.twice.at_most.times(10).
|
173
|
+
and_return { rand }
|
174
|
+
|
175
|
+
The following methods may be used to create and refine expectations on a mock
|
176
|
+
object. See theFlexMock::Expectation for more details.
|
177
|
+
|
178
|
+
* <b>should_receive(<em>method_name</em>)</b>
|
179
|
+
|
180
|
+
Declares that a message named <em>method_name</em> will be sent to the mock
|
181
|
+
object. Constraints on this expected message (called expectations) may be
|
182
|
+
chained to the +should_receive+ call.
|
183
|
+
|
184
|
+
* <b>should_receive(<em>method_name1</em>, <em>method_name2</em>, ...)</b>
|
185
|
+
|
186
|
+
Define a number of expected messages that have the same constraints.
|
187
|
+
|
188
|
+
* <b>should_receive(<em>meth1</em> => <em>result1</em>, <em>meth2</em> => <em>result2</em>, ...)</b>
|
189
|
+
|
190
|
+
Define a number of expected messages that have the same constrants, but
|
191
|
+
return different values.
|
192
|
+
|
193
|
+
* <b>should_expect { |recorder| ... }</b>
|
194
|
+
|
195
|
+
Creates a mock recording object that will translate received method calls
|
196
|
+
into mock expectations. The recorder is passed to a block supplied with the
|
197
|
+
+should_expect+ method. See examples below.
|
198
|
+
|
199
|
+
* <b>with(<em>arglist</em>)</b>
|
200
|
+
|
201
|
+
Declares that this expectation matches messages that match the given
|
202
|
+
argument list. The <tt>===</tt> operator is used on a argument by argument
|
203
|
+
basis to determine matching. This means that most literal values match
|
204
|
+
literally, class values match any instance of a class and regular expression
|
205
|
+
match any matching string (after a +to_s+ conversion). See argument
|
206
|
+
validators (below) for details on argument validation options.
|
207
|
+
|
208
|
+
* <b>with_any_args</b>
|
209
|
+
|
210
|
+
Declares that this expectation matches the message with any argument
|
211
|
+
(default)
|
212
|
+
|
213
|
+
* <b>with_no_args</b>
|
214
|
+
|
215
|
+
Declares that this expectation matches messages with no arguments
|
216
|
+
|
217
|
+
* <b>and_return(<em>value</em>)</b>
|
218
|
+
|
219
|
+
Declares that the expected message will return the given value.
|
122
220
|
|
123
|
-
* <b
|
124
|
-
sent <em>n</em> times. <tt>at_least</tt> / <tt>at_most</tt>
|
125
|
-
modifiers are allowed.
|
221
|
+
* <b>and_return(<em>value1</em>, <em>value2</em>, ...)</b>
|
126
222
|
|
127
|
-
|
128
|
-
message
|
129
|
-
|
130
|
-
|
131
|
-
often. Both <tt>at_least</tt> and <tt>at_most</tt> may be specified
|
132
|
-
on the same expectation.
|
223
|
+
Declares that the expected message will return a series of values. Each
|
224
|
+
invocation of the message will return the next value in the series. The last
|
225
|
+
value will be repeatably returned if the number of matching calls exceeds
|
226
|
+
the number of values.
|
133
227
|
|
134
|
-
* <b
|
135
|
-
|
228
|
+
* <b>and_return { |args, ...| code ... } </b>
|
229
|
+
|
230
|
+
Declares that the expected message will return the yielded value of the
|
231
|
+
block. The block will receive all the arguments in the message. If the
|
232
|
+
message was provided a block, it will be passed as the last parameter of the
|
233
|
+
block's argument list.
|
234
|
+
|
235
|
+
* <b>returns( ... )</b>
|
236
|
+
|
237
|
+
Alias for <tt>and_return</tt>.
|
238
|
+
|
239
|
+
* <b>zero_or_more_times</b>
|
240
|
+
|
241
|
+
Declares that the expected message is may be sent zero or more times
|
242
|
+
(default, equivalent to <tt>at_least.never</tt>).
|
243
|
+
|
244
|
+
* <b>once</b>
|
245
|
+
|
246
|
+
Declares that the expected message is only sent once. <tt>at_least</tt> /
|
247
|
+
<tt>at_most</tt> modifiers are allowed.
|
248
|
+
|
249
|
+
* <b>twice</b>
|
250
|
+
|
251
|
+
Declares that the expected message is only sent twice. <tt>at_least</tt> /
|
252
|
+
<tt>at_most</tt> modifiers are allowed.
|
253
|
+
|
254
|
+
* <b>never</b>
|
255
|
+
|
256
|
+
Declares that the expected message is never sent. <tt>at_least</tt> /
|
257
|
+
<tt>at_most</tt> modifiers are allowed.
|
258
|
+
|
259
|
+
* <b>times(<em>n</em>)</b>
|
260
|
+
|
261
|
+
Declares that the expected message is sent <em>n</em> times.
|
262
|
+
<tt>at_least</tt> / <tt>at_most</tt> modifiers are allowed.
|
263
|
+
|
264
|
+
* <b>at_least</b>
|
265
|
+
|
266
|
+
Modifies the immediately following message count constraint so that it means
|
267
|
+
the message is sent at least that number of times. E.g.
|
268
|
+
<tt>at_least.once</tt> means the message is sent at least once during the
|
269
|
+
test, but may be sent more often. Both <tt>at_least</tt> and
|
136
270
|
<tt>at_most</tt> may be specified on the same expectation.
|
137
271
|
|
138
|
-
* <b
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
272
|
+
* <b>at_most</b>
|
273
|
+
|
274
|
+
Similar to <tt>at_least</tt>, but puts an upper limit on the number of
|
275
|
+
messages. Both <tt>at_least</tt> and <tt>at_most</tt> may be specified on
|
276
|
+
the same expectation.
|
277
|
+
|
278
|
+
* <b>ordered</b>
|
279
|
+
|
280
|
+
Declares that the expected message is ordered and is expected to be received
|
281
|
+
in a certain position in a sequence of messages. The message should arrive
|
282
|
+
after and previously declared ordered messages and prior to any following
|
283
|
+
declared ordered messages. Unordered messages are ignored when considering
|
284
|
+
the message order.
|
285
|
+
|
286
|
+
* <b>ordered(<em>group</em>)</b>
|
287
|
+
|
288
|
+
Declare that the expected message belongs to an order group. Methods within
|
289
|
+
an order group may be received in any order. Ordered messages outside the
|
290
|
+
group must be received either before or after all of the grouped messages.
|
291
|
+
|
292
|
+
For example, in the following, messages +flip+ and +flop+ may be received in
|
293
|
+
any order (because they are in the same group), but must occur strictly
|
294
|
+
after +start+ but before +end+. The message +any_time+ may be received at
|
295
|
+
any time because it is not ordered.
|
296
|
+
|
297
|
+
m = flexmock()
|
298
|
+
m.should_receive(:any_time)
|
299
|
+
m.should_receive(:start).ordered
|
300
|
+
m.should_receive(:flip).ordered(:flip_flop_group)
|
301
|
+
m.should_receive(:flop).ordered(:flip_flop_group)
|
302
|
+
m.should_receive(:end).ordered
|
303
|
+
|
304
|
+
* <b>mock</b>
|
305
|
+
|
306
|
+
Expectation constraints always return the expectation so that the
|
307
|
+
constraints can be chained. If you wish to do a one-liner and assign the
|
308
|
+
mock to a variable, the +mock+ method on an expectation will return the
|
309
|
+
original mock object.
|
310
|
+
|
311
|
+
m = flexmock.should_receive(:hello).once.and_return("World").mock
|
312
|
+
|
162
313
|
=== Argument Validation
|
163
314
|
|
164
|
-
The values passed to the +with+ declarator determine the criteria for
|
165
|
-
|
166
|
-
|
167
|
-
method call.
|
315
|
+
The values passed to the +with+ declarator determine the criteria for matching
|
316
|
+
expectations. The first expectation found that matches the arguments in a mock
|
317
|
+
method call will be used to validate that mock method call.
|
168
318
|
|
169
319
|
The following rules are used for argument matching:
|
170
320
|
|
171
|
-
* A +with+ parameter that is a class object will match any actual
|
172
|
-
|
321
|
+
* A +with+ parameter that is a class object will match any actual argument
|
322
|
+
that is an instance of that class.
|
173
323
|
|
174
324
|
Examples:
|
175
325
|
|
176
326
|
with(Integer) will match f(3)
|
177
327
|
|
178
|
-
* A regular expression will match any actual argument that matches the
|
179
|
-
|
180
|
-
|
328
|
+
* A regular expression will match any actual argument that matches the regular
|
329
|
+
expression. Non-string actual arguments are converted to strings via +to_s+
|
330
|
+
before applying the regular expression.
|
181
331
|
|
182
332
|
Examples:
|
183
333
|
|
@@ -190,12 +340,11 @@ The following rules are used for argument matching:
|
|
190
340
|
|
191
341
|
with(3) will match f(3)
|
192
342
|
with("hello") will match f("hello")
|
193
|
-
|
194
|
-
* If you wish to override the default matching behavior and force
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
instances, not themselves.
|
343
|
+
|
344
|
+
* If you wish to override the default matching behavior and force matching by
|
345
|
+
equality, you can use the FlexMock.eq convenience method. This is mostly
|
346
|
+
used when you wish to match class objects, since the default matching
|
347
|
+
behavior for class objects is to match instances, not themselves.
|
199
348
|
|
200
349
|
Examples:
|
201
350
|
|
@@ -212,8 +361,8 @@ The following rules are used for argument matching:
|
|
212
361
|
* If you wish to match _anything_, then use the <tt>FlexMock.any</tt>
|
213
362
|
method in the with argument list.
|
214
363
|
|
215
|
-
Examples (assumes either the FlexMock::TestCase or
|
216
|
-
|
364
|
+
Examples (assumes either the FlexMock::TestCase or FlexMock::ArgumentTypes
|
365
|
+
mix-ins has been included):
|
217
366
|
|
218
367
|
with(any) will match f(3)
|
219
368
|
with(any) will match f("hello")
|
@@ -229,15 +378,17 @@ The following rules are used for argument matching:
|
|
229
378
|
|
230
379
|
will match any even integer.
|
231
380
|
|
232
|
-
===
|
381
|
+
=== Creating Partial Mocks
|
233
382
|
|
234
383
|
Sometimes it is useful to mock the behavior of one or two methods in an
|
235
|
-
existing object without changing the behavior of the rest of the object.
|
236
|
-
|
384
|
+
existing object without changing the behavior of the rest of the object. If
|
385
|
+
you pass a real object to the +flexmock+ method, it will allow you to use that
|
386
|
+
real object in your test and will just mock out the one or two methods that
|
387
|
+
you specify.
|
237
388
|
|
238
|
-
For example, suppose that a Dog object uses a Woofer object to
|
239
|
-
|
240
|
-
|
389
|
+
For example, suppose that a Dog object uses a Woofer object to bark. The code
|
390
|
+
for Dog looks like this (we will leave the code for Woofer to your
|
391
|
+
imagination):
|
241
392
|
|
242
393
|
class Dog
|
243
394
|
def initialize
|
@@ -246,109 +397,136 @@ Woofer to your imagination):
|
|
246
397
|
def bark
|
247
398
|
@woofer.woof
|
248
399
|
end
|
400
|
+
def wag
|
401
|
+
:happy
|
402
|
+
end
|
249
403
|
end
|
250
404
|
|
251
|
-
Now we want to test Dog, but using a real Woofer object in the test is
|
252
|
-
|
253
|
-
|
405
|
+
Now we want to test Dog, but using a real Woofer object in the test is a real
|
406
|
+
pain (why? ... well because Woofer plays a sound file of a dog barking, and
|
407
|
+
that's really annoying during testing).
|
254
408
|
|
255
|
-
So, how can we create a Dog object with mocked Woofer?
|
256
|
-
|
257
|
-
to return anything we want.
|
409
|
+
So, how can we create a Dog object with mocked Woofer? All we need to do is
|
410
|
+
allow FlexMock to replace the +bark+ method.
|
258
411
|
|
259
412
|
Here's the test code:
|
260
413
|
|
261
414
|
class TestDogBarking < Test::Unit::TestCase
|
262
415
|
include FlexMock::TestCase
|
263
416
|
|
264
|
-
# Setup the tests by
|
417
|
+
# Setup the tests by mocking the +new+ method of
|
265
418
|
# Woofer and return a mock woofer.
|
266
419
|
def setup
|
267
|
-
|
268
|
-
|
269
|
-
mock.should_receive(:woof).and_return(:grrrr)
|
270
|
-
end
|
271
|
-
}
|
420
|
+
@dog = Dog.new
|
421
|
+
flexmock(dog, :bark => :grrr)
|
272
422
|
end
|
273
423
|
|
274
|
-
def
|
275
|
-
assert_equal :grrrr, @dog.bark
|
424
|
+
def test_dog
|
425
|
+
assert_equal :grrrr, @dog.bark # Mocked Method
|
426
|
+
assert_equal :happy, @dog.wag # Normal Method
|
276
427
|
end
|
277
428
|
end
|
278
429
|
|
279
|
-
The nice thing about
|
280
|
-
out methods are returned to their normal state.
|
281
|
-
|
282
|
-
|
283
|
-
The stub technique was inspired by the +Stuba+ library in the +Mocha+
|
284
|
-
project.
|
285
|
-
|
286
|
-
=== Stubbing Behavior in All Instances Created by a Class Object
|
287
|
-
|
288
|
-
Sometimes you want to stub all instances created by a class object.
|
289
|
-
For example, you might wish to work with Connection objects that have
|
290
|
-
their "send" method stubbed out. However, the code under test creates
|
291
|
-
connections dynamically, so you can't stub them before the test is
|
292
|
-
run.
|
293
|
-
|
294
|
-
One approach is to stub the "new" method on the class object. The
|
295
|
-
stubbed implementation of "new" would create a mock object to be
|
296
|
-
returned as the value of "new". But since your stubbed implementation
|
297
|
-
of "new" has no access to the original behavior of new, you can't
|
298
|
-
really create stubs.
|
299
|
-
|
300
|
-
The <tt>any_instance</tt> method allows you to easily add stub
|
301
|
-
expectations to objects created by new. Here's the Connection example
|
302
|
-
using <tt>any_instance</tt>:
|
303
|
-
|
304
|
-
def test_connections
|
305
|
-
flexstub(Connection).any_instance do |new_con|
|
306
|
-
new_con.should_receive(:send).and_return(0)
|
307
|
-
end
|
308
|
-
connection = Connection.new
|
309
|
-
connection.send # This calls the stubbed version of send.
|
310
|
-
end
|
430
|
+
The nice thing about this technique is that after the test is over, the mocked
|
431
|
+
out methods are returned to their normal state. Outside the test everything is
|
432
|
+
back to normal.
|
311
433
|
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
version of the
|
434
|
+
<b>NOTE:</b> In previous versions of FlexMock, partial mocking was called
|
435
|
+
"stubs" and the +flexstub+ method was used to create the partial mocks.
|
436
|
+
Although partial mocks were often used as stubs, the terminology was not quite
|
437
|
+
correct. The current version of FlexMock uses the +flexmock+ method to create
|
438
|
+
both regular stubs and partial stubs. A version of the +flexstub+ method is
|
439
|
+
included for backwards compatibility. See Martin Fowler's article <em>Mocks
|
440
|
+
Aren't Stubs</em> (http://www.martinfowler.com/articles/mocksArentStubs.html)
|
441
|
+
for a better understanding of the difference between mocks and stubs.
|
316
442
|
|
317
|
-
|
443
|
+
This partial mocking technique was inspired by the +Stuba+ library in the
|
444
|
+
+Mocha+ project.
|
318
445
|
|
319
|
-
|
320
|
-
<em>Class Interception is now deprecated. It only worked in a
|
321
|
-
small number of cases. See the "Mocking Existing Objects"
|
322
|
-
example above for a much better approach to the same problem.
|
323
|
-
Version 0.5.x will be the last version of FlexMock that supports the
|
324
|
-
Class Interception API.</em>
|
446
|
+
=== Mocking Class Objects
|
325
447
|
|
326
|
-
|
327
|
-
|
448
|
+
In the previous example we mocked out the +bark+ method of a Dog object to
|
449
|
+
avoid invoking the Woofer object. Perhaps a better technique would be to mock
|
450
|
+
the Woofer object directly. But Dog uses Woofer explicitly so we cannot just
|
451
|
+
pass in a mock object for Dog to use.
|
328
452
|
|
329
|
-
|
453
|
+
But wait, we can add mock behavior to any existing object, and classes are
|
454
|
+
objects in Ruby. So why don't we just mock out the Woofer class object to
|
455
|
+
return mocks for us.
|
330
456
|
|
331
|
-
|
332
|
-
|
457
|
+
class TestDogBarking < Test::Unit::TestCase
|
458
|
+
include FlexMock::TestCase
|
333
459
|
|
334
|
-
|
335
|
-
|
336
|
-
|
460
|
+
# Setup the tests by mocking the +new+ method of
|
461
|
+
# Woofer and return a mock woofer.
|
462
|
+
def setup
|
463
|
+
flexmock(Woofer).should_receive(:new).
|
464
|
+
and_return(flexmock(:woof => :grrr))
|
465
|
+
@dog = Dog.new
|
466
|
+
end
|
337
467
|
|
338
|
-
|
339
|
-
|
340
|
-
|
468
|
+
def test_dog
|
469
|
+
assert_equal :grrrr, @dog.bark # Calls woof on mock object
|
470
|
+
# returned by Woofer.new
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
=== Mocking Behavior in All Instances Created by a Class Object
|
475
|
+
|
476
|
+
Sometimes returning a single mock object is not enough. Occasionally you want
|
477
|
+
to mock <em>every</em> instance object created by a class. FlexMock makes this
|
478
|
+
very easy.
|
479
|
+
|
480
|
+
class TestDogBarking < Test::Unit::TestCase
|
481
|
+
include FlexMock::TestCase
|
482
|
+
|
483
|
+
# Setup the tests by mocking Woofer to always
|
484
|
+
# return partial mocks.
|
485
|
+
def setup
|
486
|
+
flexmock(Woofer).new_instances.should_receive(:woof => :grrr)
|
487
|
+
end
|
488
|
+
|
489
|
+
def test_dog
|
490
|
+
assert_equal :grrrr, Dog.new.bark # All dog objects
|
491
|
+
assert_equal :grrrr, Dog.new.bark # are mocked.
|
492
|
+
end
|
493
|
+
end
|
494
|
+
|
495
|
+
Note that FlexMock adds the mock expectations after the original +new+ method
|
496
|
+
has completed. If the original version of +new+ yields the newly created
|
497
|
+
instance to a block, that block will get an non-mocked version of the object.
|
498
|
+
|
499
|
+
Note that +new_instances+ will accept a block if you wish to mock several
|
500
|
+
methods at the same time. E.g.
|
501
|
+
|
502
|
+
flexmock(Woofer).new_instances do |m|
|
503
|
+
m.should_receive(:woof).twice.and_return(:grrr)
|
504
|
+
m.should_receive(:wag).at_least.once.and_return(:happy)
|
505
|
+
end
|
341
506
|
|
342
507
|
== Examples
|
343
508
|
|
509
|
+
=== Create a simple mock object that returns a value for a set of method calls
|
510
|
+
|
511
|
+
require 'flexmock/test_unit'
|
512
|
+
|
513
|
+
class TestSimple < Test::Unit::TestCase
|
514
|
+
def test_simple_mock
|
515
|
+
m = flexmock(:pi => 3.1416, :e => 2.71)
|
516
|
+
assert_equal 3.1416, m.pi
|
517
|
+
assert_equal 2.71, m.e
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
344
521
|
=== Expect multiple queries and a single update
|
345
522
|
|
346
|
-
|
347
|
-
argument
|
523
|
+
Multiple calls to the query method will be allows, and calls may have any
|
524
|
+
argument list. Each call to query will return the three element array [1, 2,
|
525
|
+
3]. The call to update must have a specific argument of 5.
|
348
526
|
|
349
|
-
|
350
|
-
include FlexMock::TestCase
|
527
|
+
require 'flexmock/test_unit'
|
351
528
|
|
529
|
+
class TestDb < Test::Unit::TestCase
|
352
530
|
def test_db
|
353
531
|
db = flexmock('db')
|
354
532
|
db.should_receive(:query).and_return([1,2,3])
|
@@ -359,8 +537,8 @@ argument of 5.
|
|
359
537
|
|
360
538
|
=== Expect all queries before any updates
|
361
539
|
|
362
|
-
(This and following examples assume that the
|
363
|
-
|
540
|
+
(This and following examples assume that the 'flexmock/test_unit' file has
|
541
|
+
been required.)
|
364
542
|
|
365
543
|
All the query message must occur before any of the update messages.
|
366
544
|
|
@@ -467,25 +645,28 @@ ignoring.
|
|
467
645
|
<b>Note:</b> The original +mock_ignore_missing+ is now an alias for
|
468
646
|
+should_ignore_missing+.
|
469
647
|
|
470
|
-
|
648
|
+
=== Mock just one method on an existing object
|
471
649
|
|
472
|
-
|
473
|
-
original version of FlexMock. +mock_handle+ is equivalent to the
|
474
|
-
following:
|
650
|
+
The Portfolio class calculate the value of a set of stocks by talking to a quote service via a web service. Since we don't want to use a real web service in our unit tests, we will mock the quote service.
|
475
651
|
|
476
|
-
def
|
477
|
-
|
652
|
+
def test_portfolio_value
|
653
|
+
flexmock(QuoteService).new_instances do |m|
|
654
|
+
m.should_receive(:quote).and_return(100)
|
655
|
+
end
|
656
|
+
port = Portfolio.new
|
657
|
+
value = port.value # Portfolio calls QuoteService.quote
|
658
|
+
assert_equal 100, value
|
478
659
|
end
|
479
660
|
|
480
661
|
== Other Mock Objects
|
481
662
|
|
482
|
-
ruby-mock :: http://www.b13media.com/dev/ruby/mock.html
|
483
663
|
test-unit-mock :: http://www.deveiate.org/code/Test-Unit-Mock.shtml
|
484
664
|
mocha/stubba :: http://mocha.rubyforge.org/
|
665
|
+
Schmock :: http://rubyforge.org/projects/schmock/
|
485
666
|
|
486
667
|
== License
|
487
668
|
|
488
|
-
Copyright 2003, 2004, 2005, 2006 by Jim Weirich (jim@weirichhouse.org).
|
669
|
+
Copyright 2003, 2004, 2005, 2006, 2007 by Jim Weirich (jim@weirichhouse.org).
|
489
670
|
All rights reserved.
|
490
671
|
|
491
672
|
Permission is granted for use, copying, modification, distribution,
|