flexmock 0.2.0 → 0.2.1
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 +7 -0
- data/README +36 -9
- data/Rakefile +1 -1
- data/lib/flexmock.rb +70 -3
- data/test/test_record_mode.rb +51 -0
- data/test/test_should_receive.rb +19 -0
- metadata +3 -3
data/CHANGELOG
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
= Changes for FlexMock
|
2
2
|
|
3
|
+
== Version 0.2.1
|
4
|
+
|
5
|
+
* Added strict mode in record mode interface to facility using known
|
6
|
+
good algorithms for comparison testing.
|
7
|
+
* Improved the docs and examples. Fixed garbled first example in
|
8
|
+
README.
|
9
|
+
|
3
10
|
== Version 0.2.0
|
4
11
|
|
5
12
|
* Added record mode for building expectations.
|
data/README
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
FlexMock is a simple mock object for unit testing. The interface is
|
4
4
|
simple, but still provides a good bit of flexibility.
|
5
5
|
|
6
|
-
Version :: 0.2.
|
6
|
+
Version :: 0.2.1
|
7
7
|
|
8
8
|
= Links
|
9
9
|
|
@@ -40,10 +40,11 @@ Here's the complete example:
|
|
40
40
|
def test_tempurature_sampler
|
41
41
|
readings = [10, 12, 14]
|
42
42
|
FlexMock.use("temp") do |sensor|
|
43
|
-
sensor = FlexMock.new
|
44
43
|
sensor.should_receive(:read_temperature).and_return { readings.shift }
|
45
|
-
|
46
|
-
|
44
|
+
|
45
|
+
sampler = TemperatureSampler.new(sensor)
|
46
|
+
assert_equal 12, sampler.average_temp
|
47
|
+
end
|
47
48
|
end
|
48
49
|
end
|
49
50
|
|
@@ -226,7 +227,7 @@ All the query message must occur before any of the update messages.
|
|
226
227
|
|
227
228
|
FlexMock('db').use |db|
|
228
229
|
db.should_receive(:query).and_return([1,2,3]).ordered
|
229
|
-
db.
|
230
|
+
db.should_recieve(:update).and_return(nil).ordered
|
230
231
|
# test code here
|
231
232
|
end
|
232
233
|
|
@@ -254,19 +255,45 @@ values to figure out what value to return.
|
|
254
255
|
# test code here
|
255
256
|
end
|
256
257
|
|
257
|
-
=== Same as above, but using the
|
258
|
+
=== Same as above, but using the Record Mode interface
|
259
|
+
|
260
|
+
The record mode interface offers much the same features as the
|
261
|
+
+should_receive+ interface introduced so far, but it allows the
|
262
|
+
messages to be sent directly to a recording object rather than be
|
263
|
+
specified indirectly using a symbol.
|
258
264
|
|
259
265
|
FlexMock('db').use |db|
|
260
266
|
db.should_expect do |rec|
|
261
267
|
rec.startup.once.ordered
|
262
268
|
rec.query("CPWR") { 12.3 }.once.ordered(:queries)
|
263
269
|
rec.query("MSFT") { 10.0 }.once.ordered(:queries)
|
264
|
-
rec.query(
|
265
|
-
rec.finish
|
270
|
+
rec.query("^....$/) { 3.3 }.at_least.once.ordered(:queries)
|
271
|
+
rec.finish)once.ordered
|
266
272
|
end
|
267
|
-
# test code here
|
273
|
+
# test code here using +db+.
|
268
274
|
end
|
269
275
|
|
276
|
+
=== Using Record Mode to record a known, good algorithm for testing
|
277
|
+
|
278
|
+
Record mode is nice when you have a known, good algorithm that can use
|
279
|
+
a recording mock object to record the steps. Then you compare the
|
280
|
+
execution of a new algorithm to behavior of the old using the recorded
|
281
|
+
expectations in the mock. For this you probably want to put the
|
282
|
+
recorder in _strict_ mode so that the recorded expectations use exact
|
283
|
+
matching on argument lists, and strict ordering of the method calls.
|
284
|
+
|
285
|
+
<b>Note:</b> This is most useful when there are no queries on the mock
|
286
|
+
objects, because the query responses cannot be programmed into the
|
287
|
+
recorder object.
|
288
|
+
|
289
|
+
FlexMock.use('builder') do |builder|
|
290
|
+
builder.should_expect do |rec|
|
291
|
+
rec.should_be_strict
|
292
|
+
known_good_way_to_build_xml(rec) # record the messages
|
293
|
+
end
|
294
|
+
new_way_to_build_xml(builder) # compare to new way
|
295
|
+
end
|
296
|
+
|
270
297
|
=== Expect multiple calls, returning a different value each time
|
271
298
|
|
272
299
|
Sometimes you need to return different values for each call to a
|
data/Rakefile
CHANGED
data/lib/flexmock.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
#---
|
4
|
-
# Copyright 2003, 2004, 2005 by Jim Weirich (jim@weirichhouse.org).
|
4
|
+
# Copyright 2003, 2004, 2005, 2006 by Jim Weirich (jim@weirichhouse.org).
|
5
5
|
# All rights reserved.
|
6
6
|
|
7
7
|
# Permission is granted for use, copying, modification, distribution,
|
@@ -213,8 +213,16 @@ class FlexMock
|
|
213
213
|
end
|
214
214
|
|
215
215
|
# Invoke the expectations for a given set of arguments.
|
216
|
+
#
|
217
|
+
# First, look for an expectation that matches the arguements and
|
218
|
+
# is eligible to be called. Failing that, look for a expectation
|
219
|
+
# that matches teh arguments (at this point it will be ineligible,
|
220
|
+
# but at least we will get a good failure message). Finally,
|
221
|
+
# check for expectations that don't have any argument matching
|
222
|
+
# criteria.
|
216
223
|
def call(*args)
|
217
|
-
exp = @expectations.find { |e| e.match_args(args) } ||
|
224
|
+
exp = @expectations.find { |e| e.match_args(args) && e.eligible? } ||
|
225
|
+
@expectations.find { |e| e.match_args(args) } ||
|
218
226
|
@expectations.find { |e| e.expected_args.nil? }
|
219
227
|
FlexMock.check("no matching handler found for " +
|
220
228
|
FlexMock.format_args(@sym, args)) { ! exp.nil? }
|
@@ -315,6 +323,13 @@ class FlexMock
|
|
315
323
|
@exp = expectation
|
316
324
|
@limit = limit
|
317
325
|
end
|
326
|
+
|
327
|
+
# If the expectation has been called +n+ times, is it still
|
328
|
+
# eligible to be called again? The default answer compares n to
|
329
|
+
# the established limit.
|
330
|
+
def eligible?(n)
|
331
|
+
n < @limit
|
332
|
+
end
|
318
333
|
end
|
319
334
|
|
320
335
|
####################################################################
|
@@ -340,6 +355,14 @@ class FlexMock
|
|
340
355
|
"Method '#{@exp}' should be called at least #{@limit} times,\n" +
|
341
356
|
"only called #{n} times"
|
342
357
|
end
|
358
|
+
|
359
|
+
# If the expectation has been called +n+ times, is it still
|
360
|
+
# eligible to be called again? Since this validator only
|
361
|
+
# establishes a lower limit, not an upper limit, then the answer
|
362
|
+
# is always true.
|
363
|
+
def eligible?(n)
|
364
|
+
true
|
365
|
+
end
|
343
366
|
end
|
344
367
|
|
345
368
|
####################################################################
|
@@ -396,6 +419,12 @@ class FlexMock
|
|
396
419
|
@return_block.call(*args)
|
397
420
|
end
|
398
421
|
|
422
|
+
# Is this expectation eligible to be called again? It is eligible
|
423
|
+
# only if all of its count validators agree that it is eligible.
|
424
|
+
def eligible?
|
425
|
+
@count_validators.all? { |v| v.eligible?(@actual_count) }
|
426
|
+
end
|
427
|
+
|
399
428
|
# Validate that the order
|
400
429
|
def validate_order
|
401
430
|
return if @order_number.nil?
|
@@ -569,15 +598,53 @@ class FlexMock
|
|
569
598
|
# mock object.
|
570
599
|
#
|
571
600
|
class Recorder
|
601
|
+
include FlexMock::ArgumentTypes
|
602
|
+
|
572
603
|
# Create a method recorder for the mock +mock+.
|
573
604
|
def initialize(mock)
|
574
605
|
@mock = mock
|
606
|
+
@strict = false
|
607
|
+
end
|
608
|
+
|
609
|
+
# Place the record in strict mode. While recording expectations
|
610
|
+
# in strict mode, the following will be true.
|
611
|
+
#
|
612
|
+
# * All expectations will be expected in the order they were
|
613
|
+
# recorded.
|
614
|
+
# * All expectations will be expected once.
|
615
|
+
# * All arguments will be placed in exact match mode,
|
616
|
+
# including regular expressions and class objects.
|
617
|
+
#
|
618
|
+
# Strict mode is usually used when giving the recorder to a known
|
619
|
+
# good algorithm. Strict mode captures the exact sequence of
|
620
|
+
# calls and validate that the code under test performs the exact
|
621
|
+
# same sequence of calls.
|
622
|
+
#
|
623
|
+
# The recorder may exit strict mode via a
|
624
|
+
# <tt>should_be_strict(false)</tt> call. Non-strict expectations
|
625
|
+
# may be recorded at that point, or even explicit expectations
|
626
|
+
# (using +should_receieve+) can be specified.
|
627
|
+
#
|
628
|
+
def should_be_strict(is_strict=true)
|
629
|
+
@strict = is_strict
|
630
|
+
end
|
631
|
+
|
632
|
+
# Is the recorder in strict mode?
|
633
|
+
def strict?
|
634
|
+
@strict
|
575
635
|
end
|
576
636
|
|
577
637
|
# Record an expectation for receiving the method +sym+ with the
|
578
638
|
# given arguments.
|
579
639
|
def method_missing(sym, *args, &block)
|
580
|
-
@mock.should_receive(sym).and_return(&block)
|
640
|
+
expectation = @mock.should_receive(sym).and_return(&block)
|
641
|
+
if @strict
|
642
|
+
args = args.collect { |arg| eq(arg) }
|
643
|
+
expectation.with(*args).ordered.once
|
644
|
+
else
|
645
|
+
expectation.with(*args)
|
646
|
+
end
|
647
|
+
expectation
|
581
648
|
end
|
582
649
|
end
|
583
650
|
|
data/test/test_record_mode.rb
CHANGED
@@ -106,4 +106,55 @@ class TestRecordMode < Test::Unit::TestCase
|
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
109
|
+
def test_strict_record_mode_requires_exact_argument_matches
|
110
|
+
assert_fails do
|
111
|
+
FlexMock.use("mock") do |mock|
|
112
|
+
mock.should_expect do |rec|
|
113
|
+
rec.should_be_strict
|
114
|
+
rec.f(Integer)
|
115
|
+
end
|
116
|
+
mock.f(3)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_strict_record_mode_requires_exact_ordering
|
122
|
+
assert_fails do
|
123
|
+
FlexMock.use("mock") do |mock|
|
124
|
+
mock.should_expect do |rec|
|
125
|
+
rec.should_be_strict
|
126
|
+
rec.f(1)
|
127
|
+
rec.f(2)
|
128
|
+
end
|
129
|
+
mock.f(2)
|
130
|
+
mock.f(1)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_strict_record_mode_requires_once
|
136
|
+
assert_fails do
|
137
|
+
FlexMock.use("mock") do |mock|
|
138
|
+
mock.should_expect do |rec|
|
139
|
+
rec.should_be_strict
|
140
|
+
rec.f(1)
|
141
|
+
end
|
142
|
+
mock.f(1)
|
143
|
+
mock.f(1)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_strict_record_mode_can_not_fail
|
149
|
+
FlexMock.use("mock") do |mock|
|
150
|
+
mock.should_expect do |rec|
|
151
|
+
rec.should_be_strict
|
152
|
+
rec.f(Integer)
|
153
|
+
rec.f(2)
|
154
|
+
end
|
155
|
+
mock.f(Integer)
|
156
|
+
mock.f(2)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
109
160
|
end
|
data/test/test_should_receive.rb
CHANGED
@@ -507,6 +507,25 @@ class TestFlexMockShoulds < Test::Unit::TestCase
|
|
507
507
|
assert_equal 'f(1, "two", /^3$/)', exp.to_s
|
508
508
|
end
|
509
509
|
|
510
|
+
def test_explicit_ordering_with_limits_allow_multiple_return_values
|
511
|
+
FlexMock.use('mock') do |m|
|
512
|
+
m.should_receive(:f).with(2).once.and_return { :first_time }
|
513
|
+
m.should_receive(:f).with(2).twice.and_return { :second_or_third_time }
|
514
|
+
m.should_receive(:f).with(2).and_return { :forever }
|
515
|
+
|
516
|
+
assert_equal :first_time, m.f(2)
|
517
|
+
assert_equal :second_or_third_time, m.f(2)
|
518
|
+
assert_equal :second_or_third_time, m.f(2)
|
519
|
+
assert_equal :forever, m.f(2)
|
520
|
+
assert_equal :forever, m.f(2)
|
521
|
+
assert_equal :forever, m.f(2)
|
522
|
+
assert_equal :forever, m.f(2)
|
523
|
+
assert_equal :forever, m.f(2)
|
524
|
+
assert_equal :forever, m.f(2)
|
525
|
+
assert_equal :forever, m.f(2)
|
526
|
+
end
|
527
|
+
end
|
528
|
+
|
510
529
|
def assert_failure
|
511
530
|
assert_raises(Test::Unit::AssertionFailedError) do yield end
|
512
531
|
end
|
metadata
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.8.11.
|
2
|
+
rubygems_version: 0.8.11.5
|
3
3
|
specification_version: 1
|
4
4
|
name: flexmock
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.2.
|
6
|
+
version: 0.2.1
|
7
7
|
date: 2006-03-21 00:00:00 -05:00
|
8
8
|
summary: Simple and Flexible Mock Objects for Testing
|
9
9
|
require_paths:
|
@@ -32,8 +32,8 @@ files:
|
|
32
32
|
- Rakefile
|
33
33
|
- README
|
34
34
|
- lib/flexmock.rb
|
35
|
-
- test/test_record_mode.rb
|
36
35
|
- test/test_should_receive.rb
|
36
|
+
- test/test_record_mode.rb
|
37
37
|
- test/test_samples.rb
|
38
38
|
- test/test_mock.rb
|
39
39
|
- test/test_naming.rb
|