flexmock 0.1.7 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data/CHANGELOG +5 -0
  2. data/README +166 -52
  3. data/Rakefile +12 -2
  4. data/lib/flexmock.rb +40 -1
  5. data/test/test_record_mode.rb +109 -0
  6. metadata +34 -30
data/CHANGELOG CHANGED
@@ -1,5 +1,10 @@
1
1
  = Changes for FlexMock
2
2
 
3
+ == Version 0.2.0
4
+
5
+ * Added record mode for building expectations.
6
+ * Fixed a bunch of documentation.
7
+
3
8
  == Version 0.1.7
4
9
 
5
10
  * Bumped version because 0.1.6 was uploaded to the wrong Rubyforge area.
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.1.7
6
+ Version :: 0.2.0
7
7
 
8
8
  = Links
9
9
 
@@ -49,62 +49,163 @@ Here's the complete example:
49
49
 
50
50
  == Quick Reference
51
51
 
52
- The following declarators may be used to create the proper
53
- expectations on a FlexMock object.
52
+ === Expectation Declarators
54
53
 
55
- * <tt>should_receive(<em>symbol</em>)</tt> -- Declares that a message
56
- named <em>symbol</em> will be sent to the mock object. Further
57
- refinements on this expected message (called an expectation) may be
58
- chained to the +should_receive+ call.
59
- * <tt>with(<em>arglist</em>)</tt> -- Declares that this expectation
60
- matches messages that match the given argument list. The
61
- <tt>===</tt> operator is used on a argument by argument basis to
54
+ Expectation declarators are used to specify the expectations placed
55
+ upon received method calls. The following declarators may be used to
56
+ create the proper expectations on a FlexMock object.
57
+
58
+ * <b><tt>should_receive(<em>symbol</em>)</tt></b> -- Declares that a
59
+ message named <em>symbol</em> will be sent to the mock object.
60
+ Further refinements on this expected message (called an expectation)
61
+ may be chained to the +should_receive+ call.
62
+
63
+ * <b><tt>should_expect</tt></b> -- Creates a mock recording object
64
+ that will translate received method calls into mock expectations.
65
+ The recorder is passed to a block supplied with the +should_expect+
66
+ method. See examples below.
67
+
68
+ * <b><tt>with(<em>arglist</em>)</tt></b> -- Declares that this
69
+ expectation matches messages that match the given argument list.
70
+ The <tt>===</tt> operator is used on a argument by argument basis to
62
71
  determine matching. This means that most literal values match
63
72
  literally, class values match any instance of a class and regular
64
73
  expression match any matching string (after a +to_s+ conversion).
65
- * <tt>with_any_args</tt> -- Declares that this expectation matches the
66
- message with any argument (default)
67
- * <tt>with_no_args</tt> -- Declares that this expectation matches
68
- messages with no arguments
69
- * <tt>returns(<em>value</em>)</tt> -- Declares that the message will
70
- return the given value (<tt>returns(nil)</tt> is the default).
71
- * <tt>returns { code ... }</tt> -- Declares that the message will
72
- return whatever the block calculates.
73
- * <tt>zero_or_more_times</tt> -- Declares that the message is may be
74
- sent zero or more times (default, equivalent to
74
+ See argument validators (below) for details on argument validation
75
+ options.
76
+
77
+ * <b><tt>with_any_args</tt></b> -- Declares that this expectation
78
+ matches the message with any argument (default)
79
+
80
+ * <b><tt>with_no_args</tt></b> -- Declares that this expectation
81
+ matches messages with no arguments
82
+
83
+ * <b><tt>returns(<em>value</em>)</tt></b> -- Declares that the message
84
+ will return the given value (<tt>returns(nil)</tt> is the default).
85
+
86
+ * <b><tt>returns { |args| code ... }</tt></b> -- Declares that the
87
+ message will return whatever the block calculates. The actual
88
+ arguments in the message will be passed to the block.
89
+
90
+ * <b><tt>zero_or_more_times</tt></b> -- Declares that the message is
91
+ may be sent zero or more times (default, equivalent to
75
92
  <tt>at_least.never</tt>).
76
- * <tt>once</tt> -- Declares that the message is only sent once.
77
- <tt>at_least</tt> / <tt>at_most</tt> modifiers are allowed.
78
- * <tt>twice</tt> -- Declares that the message is only sent twice.
93
+
94
+ * <b><tt>once</tt></b> -- Declares that the message is only sent once.
79
95
  <tt>at_least</tt> / <tt>at_most</tt> modifiers are allowed.
80
- * <tt>never</tt> -- Declares that the message is never sent.
96
+
97
+ * <b><tt>twice</tt></b> -- Declares that the message is only sent
98
+ twice. <tt>at_least</tt> / <tt>at_most</tt> modifiers are allowed.
99
+
100
+ * <b><tt>never</tt></b> -- Declares that the message is never sent.
81
101
  <tt>at_least</tt> / <tt>at_most</tt> modifiers are allowed.
82
- * <tt>times(<em>n</em>)</tt> -- Declares that the message is sent
83
- <em>n</em> times. <tt>at_least</tt> / <tt>at_most</tt> modifiers
84
- are allowed.
85
- * <tt>at_least</tt> -- Modifies the immediately following message
86
- count declarator so that it means the message is sent at least that
87
- number of times. E.g. <tt>at_least.once</tt> means the message is
88
- sent at least once during the test, but may be sent more often.
89
- Both <tt>at_least</tt> and <tt>at_most</tt> may be specified on the
90
- same expectation.
91
- * <tt>at_most</tt> -- Similar to <tt>at_least</tt>, but puts an upper
92
- limit on the number of messages. Both <tt>at_least</tt> and
102
+
103
+ * <b><tt>times(<em>n</em>)</tt></b> -- Declares that the message is
104
+ sent <em>n</em> times. <tt>at_least</tt> / <tt>at_most</tt>
105
+ modifiers are allowed.
106
+
107
+ * <b><tt>at_least</tt></b> -- Modifies the immediately following
108
+ message count declarator so that it means the message is sent at
109
+ least that number of times. E.g. <tt>at_least.once</tt> means the
110
+ message is sent at least once during the test, but may be sent more
111
+ often. Both <tt>at_least</tt> and <tt>at_most</tt> may be specified
112
+ on the same expectation.
113
+
114
+ * <b><tt>at_most</tt></b> -- Similar to <tt>at_least</tt>, but puts an
115
+ upper limit on the number of messages. Both <tt>at_least</tt> and
93
116
  <tt>at_most</tt> may be specified on the same expectation.
94
- * <tt>ordered</tt> -- Declares that the message is ordered and is
95
- expected to be received in a certain position in a sequence of
117
+
118
+ * <b><tt>ordered</tt></b> -- Declares that the message is ordered and
119
+ is expected to be received in a certain position in a sequence of
96
120
  messages. The message should arrive after and previously declared
97
121
  ordered messages and prior to any following declared ordered
98
122
  messages. Unordered messages are ignored when considering the
99
123
  message order.
100
- * <tt>ordered(<em>n</em>)</tt> -- Declares that the message is ordered
101
- with a specific order number. Order numbers are normally supplied
102
- sequentially starting with 1. Explicitly ordered messages must have
103
- a sequence number greater than the prior implicit order number.
104
- Using explicit order allows messages to be grouped so that the order
105
- of messages in a group (sharing an order number) can be received in
106
- any sequence, but the order between groups is still maintained. See
107
- the explicit ordering example below.
124
+
125
+ * <b><tt>ordered(<em>group</em>)</tt></b> -- Declare that the given
126
+ method belongs to an order group. Methods within the group may be
127
+ received in any order. Ordered messages outside the group must be
128
+ received either before or after the grouped messages.
129
+
130
+ For example, in the following, messages +flip+ and +flop+ may be
131
+ received in any order (because they are in the same group), but must
132
+ occur strictly after +start+ but before +end+. The message
133
+ +any_time+ may be received at any time because it is not ordered.
134
+
135
+ m = FlexMock.new
136
+ m.should_receive(:any_time)
137
+ m.should_receive(:start).ordered
138
+ m.should_receive(:flip).ordered(:flip_flop_group)
139
+ m.should_receive(:flop).ordered(:flip_flop_group)
140
+ m.should_receive(:end).ordered
141
+
142
+ === Argument Validation
143
+
144
+ The values passed to the +with+ declarator determine the criteria for
145
+ matching expectations. The first expectation found that matches the
146
+ arguments in a mock method call will be used to validate that mock
147
+ method call.
148
+
149
+ The following rules are used for argument matching:
150
+
151
+ * A +with+ parameter that is a class object will match any actual
152
+ argument that is an instance of that class.
153
+
154
+ Examples:
155
+
156
+ with(Integer) will match f(3)
157
+
158
+ * A regular expression will match any actual argument that matches the
159
+ regular expression. Non-string actual arguments are converted to
160
+ strings via +to_s+ before applying the regular expression.
161
+
162
+ Examples:
163
+
164
+ with(/^src/) will match f("src_object")
165
+ with(/^3\./) will match f(3.1415972)
166
+
167
+ * Most other objects will match based on equal values.
168
+
169
+ Examples:
170
+
171
+ with(3) will match f(3)
172
+ with("hello") will match f("hello")
173
+
174
+ * If you wish to override the default matching behavior and force
175
+ matching by equality, you can use teh FlexMock.eq convenience
176
+ method. This is mostly used when you wish to match class objects,
177
+ since the default matching behavior for class objects is to match
178
+ instances, not themselves.
179
+
180
+ Examples:
181
+
182
+ with(FlexMock.eq(Integer)) will match f(Integer)
183
+ with(FlexMock.eq(Integer)) will NOT match f(3)
184
+
185
+ If the user includes the FlexMock::ArgumentTypes module in the test
186
+ class, the above examples can be shortened to:
187
+
188
+ with(eq(Integer)) will match f(Integer)
189
+ with(eq(Integer)) will NOT match f(3)
190
+
191
+ * If you wish to match _anything_, then use the <tt>FlexMock.any</tt>
192
+ method in the with argument list.
193
+
194
+ Examples (assumes FlexMock::ArguementTypes has been included):
195
+
196
+ with(any) will match f(3)
197
+ with(any) will match f("hello")
198
+ with(any) will match f(Integer)
199
+ with(any) will match f(nil)
200
+
201
+ * If you wish to specify a complex matching criteria, use the
202
+ <tt>FlexMock.on(&block)</tt> with the logic contained in the block.
203
+
204
+ Examples (assumes FlexMock::ArguementTypes has been included):
205
+
206
+ with(on { |arg| (arg % 2) == 0 } )
207
+
208
+ will match any even integer.
108
209
 
109
210
  == Examples
110
211
 
@@ -115,7 +216,7 @@ argument of 5.
115
216
 
116
217
  FlexMock('db').use |db|
117
218
  db.should_receive(:query).and_return([1,2,3])
118
- db.should_recieve(:update).with(5).and_return(nil).once
219
+ db.should_receive(:update).with(5).and_return(nil).once
119
220
  # test code here
120
221
  end
121
222
 
@@ -125,18 +226,18 @@ All the query message must occur before any of the update messages.
125
226
 
126
227
  FlexMock('db').use |db|
127
228
  db.should_receive(:query).and_return([1,2,3]).ordered
128
- db.should_recieve(:update).and_return(nil).ordered
229
+ db.should_receive(:update).and_return(nil).ordered
129
230
  # test code here
130
231
  end
131
232
 
132
233
  === Expect several queries with different parameters
133
234
 
134
235
  The queries should happen after startup but before finish. The
135
- queries themselves may happen in any order (because they have the same
136
- order number). The first two queries should happen exactly once, but
137
- the third query (which matches any query call with a four character
138
- parameter) may be called multiple times (but at least once). Startup
139
- and finish must also happen exactly once.
236
+ queries themselves may happen in any order (because they are in the
237
+ same order group). The first two queries should happen exactly once,
238
+ but the third query (which matches any query call with a four
239
+ character parameter) may be called multiple times (but at least once).
240
+ Startup and finish must also happen exactly once.
140
241
 
141
242
  Also note that we use the +with+ method to match different arguement
142
243
  values to figure out what value to return.
@@ -153,6 +254,19 @@ values to figure out what value to return.
153
254
  # test code here
154
255
  end
155
256
 
257
+ === Same as above, but using the record mode interface
258
+
259
+ FlexMock('db').use |db|
260
+ db.should_expect do |rec|
261
+ rec.startup.once.ordered
262
+ rec.query("CPWR") { 12.3 }.once.ordered(:queries)
263
+ rec.query("MSFT") { 10.0 }.once.ordered(:queries)
264
+ rec.query(/^....$/) { 3.3 }.at_least.once.ordered(:queries)
265
+ rec.finish.once.ordered
266
+ end
267
+ # test code here
268
+ end
269
+
156
270
  === Expect multiple calls, returning a different value each time
157
271
 
158
272
  Sometimes you need to return different values for each call to a
data/Rakefile CHANGED
@@ -8,7 +8,7 @@ require 'rake/testtask'
8
8
 
9
9
  CLOBBER.include("html", 'pkg')
10
10
 
11
- PKG_VERSION = '0.1.7'
11
+ PKG_VERSION = '0.2.0'
12
12
 
13
13
  PKG_FILES = FileList[
14
14
  '[A-Z]*',
@@ -52,7 +52,7 @@ end
52
52
 
53
53
  task :rdoc => ["README"]
54
54
  file "README" => ["Rakefile"] do
55
- ruby %{-i.bak -pe 'sub!(/^Version *:: *(\\d+\\.)+\\d+ *$/, "Version :: #{PKG_VERSION}")' README}
55
+ ruby %{-i.bak -pe 'sub!(/^Version *:: *(\\d+\\.)+\\d+ *$/, "Version :: #{PKG_VERSION}")' README} # "
56
56
  end
57
57
 
58
58
  # Package Task -------------------------------------------------------
@@ -112,6 +112,12 @@ else
112
112
  end
113
113
  end
114
114
 
115
+ desc "Display a list of all the rubyfiles in the project."
116
+ task :rubyfiles do
117
+ puts FileList['**/*.rb']
118
+ end
119
+ task :rf => :rubyfiles
120
+
115
121
  require 'rake/contrib/publisher'
116
122
  require 'rake/contrib/sshpublisher'
117
123
 
@@ -129,4 +135,8 @@ task :publish => [:rdoc] do
129
135
  blurb_publisher.upload
130
136
  end
131
137
 
138
+ SVNHOME = 'svn://localhost/software/flexmock'
132
139
 
140
+ task :tag do
141
+ sh %{svn copy #{SVNHOME}/trunk #{SVNHOME}/tags/rel-#{PKG_VERSION} -m 'Release #{PKG_VERSION}'}
142
+ end
@@ -30,6 +30,9 @@ require 'test/unit'
30
30
  # m.should_receive(:downcase).with(String).
31
31
  # returns { |s| s.downcase }.once
32
32
  #
33
+ class FlexMock
34
+ end
35
+
33
36
  class FlexMock
34
37
  include Test::Unit::Assertions
35
38
 
@@ -118,6 +121,22 @@ class FlexMock
118
121
  result
119
122
  end
120
123
 
124
+ # Declare that the mock object should expect methods by providing a
125
+ # recorder for the methods and having the user invoke the expected
126
+ # methods in a block. Further expectations may be applied the
127
+ # result of the recording call.
128
+ #
129
+ # Example Usage:
130
+ #
131
+ # mock.should_expect do |record|
132
+ # record.add(Integer, 4) { |a, b|
133
+ # a + b
134
+ # }.at_least.once
135
+ #
136
+ def should_expect
137
+ yield Recorder.new(self)
138
+ end
139
+
121
140
  class << self
122
141
  include Test::Unit::Assertions
123
142
 
@@ -279,6 +298,9 @@ class FlexMock
279
298
  EqualMatcher.new(obj)
280
299
  end
281
300
 
301
+ # Return an argument matcher that matches any object, that when
302
+ # passed to the supplied block, will cause the block to return
303
+ # true.
282
304
  def on(&block)
283
305
  ProcMatcher.new(&block)
284
306
  end
@@ -514,7 +536,7 @@ class FlexMock
514
536
  # (e.g. specifying that a group of messages may be received in any
515
537
  # order as long as they all come after another group of messages),
516
538
  # a _group_ _name_ may be specified in the +ordered+ calls. All
517
- # messages within the same group may be recieved in any order.
539
+ # messages within the same group may be received in any order.
518
540
  #
519
541
  # For example, in the following, messages +flip+ and +flop+ may be
520
542
  # received in any order (because they are in the same group), but
@@ -542,5 +564,22 @@ class FlexMock
542
564
  end
543
565
  end
544
566
 
567
+ ####################################################################
568
+ # Translate arbitrary method calls into expectations on the given
569
+ # mock object.
570
+ #
571
+ class Recorder
572
+ # Create a method recorder for the mock +mock+.
573
+ def initialize(mock)
574
+ @mock = mock
575
+ end
576
+
577
+ # Record an expectation for receiving the method +sym+ with the
578
+ # given arguments.
579
+ def method_missing(sym, *args, &block)
580
+ @mock.should_receive(sym).and_return(&block).with(*args)
581
+ end
582
+ end
583
+
545
584
  extend ArgumentTypes
546
585
  end
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+ require 'flexmock'
5
+
6
+ module FailureAssertion
7
+ private
8
+ def assert_fails
9
+ assert_raise(Test::Unit::AssertionFailedError) do
10
+ yield
11
+ end
12
+ end
13
+ end
14
+
15
+ class TestRecordMode < Test::Unit::TestCase
16
+ include FlexMock::ArgumentTypes
17
+ include FailureAssertion
18
+
19
+ def test_recording_mode_works
20
+ FlexMock.use("mock") do |mock|
21
+ mock.should_expect do |r|
22
+ r.f { :answer }
23
+ end
24
+ assert_equal :answer, mock.f
25
+ end
26
+ end
27
+
28
+ def test_arguments_are_passed_to_recording_mode_block
29
+ FlexMock.new("mock") do |mock|
30
+ mock.should_expect do |recorder|
31
+ recorder.f do |arg|
32
+ assert_equal :arg, arg
33
+ :answer
34
+ end
35
+ end
36
+ assert_equal :answer, f(:arg)
37
+ end
38
+ end
39
+
40
+ def test_recording_mode_handles_multiple_returns
41
+ FlexMock.use("mock") do |mock|
42
+ mock.should_expect do |r|
43
+ answers = [1, 2]
44
+ r.f { answers.shift }
45
+ end
46
+ assert_equal 1, mock.f
47
+ assert_equal 2, mock.f
48
+ end
49
+ end
50
+
51
+ def test_recording_mode_does_not_specify_order
52
+ FlexMock.use("mock") do |mock|
53
+ mock.should_expect do |r|
54
+ r.f { 1 }
55
+ r.g { 2 }
56
+ end
57
+ assert_equal 2, mock.g
58
+ assert_equal 1, mock.f
59
+ end
60
+ end
61
+
62
+ def test_recording_mode_gets_block_args_too
63
+ FlexMock.use("mock") do |mock|
64
+ mock.should_expect do |r|
65
+ r.f(1, Proc) { |arg, block|
66
+ assert_not_nil block
67
+ block.call
68
+ }
69
+ end
70
+
71
+ assert_equal :block_result, mock.f(1) { :block_result }
72
+ end
73
+ end
74
+
75
+ def test_recording_mode_should_validate_args_with_equals
76
+ assert_fails do
77
+ FlexMock.use("mock") do |mock|
78
+ mock.should_expect do |r|
79
+ r.f(1)
80
+ end
81
+ mock.f(2)
82
+ end
83
+ end
84
+ end
85
+
86
+ def test_recording_mode_should_allow_arg_contraint_validation
87
+ assert_fails do
88
+ FlexMock.use("mock") do |mock|
89
+ mock.should_expect do |r|
90
+ r.f(1)
91
+ end
92
+ mock.f(2)
93
+ end
94
+ end
95
+ end
96
+
97
+ def test_recording_mode_should_handle_multiplicity_contraints
98
+ assert_fails do
99
+ FlexMock.use("mock") do |mock|
100
+ mock.should_expect do |r|
101
+ r.f { :result }.once
102
+ end
103
+ mock.f
104
+ mock.f
105
+ end
106
+ end
107
+ end
108
+
109
+ end
metadata CHANGED
@@ -1,57 +1,61 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.8.11.3
2
+ rubygems_version: 0.8.11.6
3
3
  specification_version: 1
4
4
  name: flexmock
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.7
7
- date: 2005-11-13 00:00:00 -05:00
6
+ version: 0.2.0
7
+ date: 2006-03-21 00:00:00 -05:00
8
8
  summary: Simple and Flexible Mock Objects for Testing
9
9
  require_paths:
10
- - lib
10
+ - lib
11
11
  email: jim@weirichhouse.org
12
12
  homepage: http://onestepback.org/software/flexmock
13
13
  rubyforge_project:
14
- description: "FlexMock is a extremely simple mock object class compatible with the Test::Unit
15
- framework. Although the FlexMock's interface is simple, it is very flexible."
14
+ description: FlexMock is a extremely simple mock object class compatible with the Test::Unit framework. Although the FlexMock's interface is simple, it is very flexible.
16
15
  autorequire:
17
16
  default_executable:
18
17
  bindir: bin
19
18
  has_rdoc: true
20
19
  required_ruby_version: !ruby/object:Gem::Version::Requirement
21
20
  requirements:
22
- -
23
- - ">"
24
- - !ruby/object:Gem::Version
25
- version: 0.0.0
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
26
24
  version:
27
25
  platform: ruby
28
26
  signing_key:
29
27
  cert_chain:
30
28
  authors:
31
- - Jim Weirich
29
+ - Jim Weirich
32
30
  files:
33
- - README
34
- - Rakefile
35
- - CHANGELOG
36
- - lib/flexmock.rb
37
- - test/test_mock.rb
38
- - test/test_example.rb
39
- - test/test_naming.rb
40
- - test/test_samples.rb
41
- - test/test_should_receive.rb
42
- - flexmock.blurb
43
- - install.rb
31
+ - CHANGELOG
32
+ - Rakefile
33
+ - README
34
+ - lib/flexmock.rb
35
+ - test/test_record_mode.rb
36
+ - test/test_should_receive.rb
37
+ - test/test_samples.rb
38
+ - test/test_mock.rb
39
+ - test/test_naming.rb
40
+ - test/test_example.rb
41
+ - flexmock.blurb
42
+ - install.rb
44
43
  test_files: []
44
+
45
45
  rdoc_options:
46
- - "--title"
47
- - Flex Mock
48
- - "--main"
49
- - README
50
- - "--line-numbers"
46
+ - --title
47
+ - Flex Mock
48
+ - --main
49
+ - README
50
+ - --line-numbers
51
51
  extra_rdoc_files:
52
- - README
53
- - CHANGELOG
52
+ - CHANGELOG
53
+ - README
54
54
  executables: []
55
+
55
56
  extensions: []
57
+
56
58
  requirements: []
57
- dependencies: []
59
+
60
+ dependencies: []
61
+