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
@@ -0,0 +1,334 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#---
|
4
|
+
# Copyright 2003, 2004, 2005, 2006, 2007 by Jim Weirich (jim@weirichhouse.org).
|
5
|
+
# All rights reserved.
|
6
|
+
|
7
|
+
# Permission is granted for use, copying, modification, distribution,
|
8
|
+
# and distribution of modified versions of this work as long as the
|
9
|
+
# above copyright notice is included.
|
10
|
+
#+++
|
11
|
+
|
12
|
+
require 'flexmock/noop'
|
13
|
+
|
14
|
+
class FlexMock
|
15
|
+
|
16
|
+
####################################################################
|
17
|
+
# An Expectation is returned from each +should_receive+ message sent
|
18
|
+
# to mock object. Each expectation records how a message matching
|
19
|
+
# the message name (argument to +should_receive+) and the argument
|
20
|
+
# list (given by +with+) should behave. Mock expectations can be
|
21
|
+
# recorded by chaining the declaration methods defined in this
|
22
|
+
# class.
|
23
|
+
#
|
24
|
+
# For example:
|
25
|
+
#
|
26
|
+
# mock.should_receive(:meth).with(args).and_returns(result)
|
27
|
+
#
|
28
|
+
class Expectation
|
29
|
+
|
30
|
+
attr_reader :expected_args, :order_number
|
31
|
+
attr_accessor :mock
|
32
|
+
|
33
|
+
# Create an expectation for a method named +sym+.
|
34
|
+
def initialize(mock, sym)
|
35
|
+
@mock = mock
|
36
|
+
@sym = sym
|
37
|
+
@expected_args = nil
|
38
|
+
@count_validators = []
|
39
|
+
@count_validator_class = ExactCountValidator
|
40
|
+
@actual_count = 0
|
41
|
+
@return_value = nil
|
42
|
+
@return_block = lambda { @return_value }
|
43
|
+
@order_number = nil
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_s
|
47
|
+
FlexMock.format_args(@sym, @expected_args)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Verify the current call with the given arguments matches the
|
51
|
+
# expectations recorded in this object.
|
52
|
+
def verify_call(*args)
|
53
|
+
validate_order
|
54
|
+
@actual_count += 1
|
55
|
+
@return_block.call(*args)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Is this expectation eligible to be called again? It is eligible
|
59
|
+
# only if all of its count validators agree that it is eligible.
|
60
|
+
def eligible?
|
61
|
+
@count_validators.all? { |v| v.eligible?(@actual_count) }
|
62
|
+
end
|
63
|
+
|
64
|
+
# Validate that the order
|
65
|
+
def validate_order
|
66
|
+
return if @order_number.nil?
|
67
|
+
FlexMock.check("method #{to_s} called out of order " +
|
68
|
+
"(expected order #{@order_number}, was #{@mock.mock_current_order})") {
|
69
|
+
@order_number >= @mock.mock_current_order
|
70
|
+
}
|
71
|
+
@mock.mock_current_order = @order_number
|
72
|
+
end
|
73
|
+
private :validate_order
|
74
|
+
|
75
|
+
# Validate the correct number of calls have been made. Called by
|
76
|
+
# the teardown process.
|
77
|
+
def mock_verify
|
78
|
+
@count_validators.each do |v|
|
79
|
+
v.validate(@actual_count)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Does the argument list match this expectation's argument
|
84
|
+
# specification.
|
85
|
+
def match_args(args)
|
86
|
+
# TODO: Rethink this:
|
87
|
+
# return false if @expected_args.nil?
|
88
|
+
return true if @expected_args.nil?
|
89
|
+
return false if args.size != @expected_args.size
|
90
|
+
(0...args.size).all? { |i| match_arg(@expected_args[i], args[i]) }
|
91
|
+
end
|
92
|
+
|
93
|
+
# Does the expected argument match the corresponding actual value.
|
94
|
+
def match_arg(expected, actual)
|
95
|
+
expected === actual ||
|
96
|
+
expected == actual ||
|
97
|
+
( Regexp === expected && expected === actual.to_s )
|
98
|
+
end
|
99
|
+
|
100
|
+
# Declare that the method should expect the given argument list.
|
101
|
+
def with(*args)
|
102
|
+
@expected_args = args
|
103
|
+
self
|
104
|
+
end
|
105
|
+
|
106
|
+
# Declare that the method should be called with no arguments.
|
107
|
+
def with_no_args
|
108
|
+
with
|
109
|
+
end
|
110
|
+
|
111
|
+
# Declare that the method can be called with any number of
|
112
|
+
# arguments of any type.
|
113
|
+
def with_any_args
|
114
|
+
@expected_args = nil
|
115
|
+
self
|
116
|
+
end
|
117
|
+
|
118
|
+
# :call-seq:
|
119
|
+
# and_return(value)
|
120
|
+
# and_return(value, value, ...)
|
121
|
+
# and_return { |*args| code }
|
122
|
+
#
|
123
|
+
# Declare that the method returns a particular value (when the
|
124
|
+
# argument list is matched).
|
125
|
+
#
|
126
|
+
# * If a single value is given, it will be returned for all matching
|
127
|
+
# calls.
|
128
|
+
# * If multiple values are given, each value will be returned in turn for
|
129
|
+
# each successive call. If the number of matching calls is greater
|
130
|
+
# than the number of values, the last value will be returned for
|
131
|
+
# the extra matching calls.
|
132
|
+
# * If a block is given, it is evaluated on each call and its
|
133
|
+
# value is returned.
|
134
|
+
#
|
135
|
+
# For example:
|
136
|
+
#
|
137
|
+
# mock.should_receive(:f).returns(12) # returns 12
|
138
|
+
#
|
139
|
+
# mock.should_receive(:f).with(String). # returns an
|
140
|
+
# returns { |str| str.upcase } # upcased string
|
141
|
+
#
|
142
|
+
# +and_return+ is an alias for +returns+.
|
143
|
+
#
|
144
|
+
def and_return(*args, &block)
|
145
|
+
@return_block =
|
146
|
+
if block_given?
|
147
|
+
block
|
148
|
+
else
|
149
|
+
lambda { args.size == 1 ? args.first : args.shift }
|
150
|
+
end
|
151
|
+
self
|
152
|
+
end
|
153
|
+
alias :returns :and_return # :nodoc:
|
154
|
+
|
155
|
+
# Declare that the method may be called any number of times.
|
156
|
+
def zero_or_more_times
|
157
|
+
at_least.never
|
158
|
+
end
|
159
|
+
|
160
|
+
# Declare that the method is called +limit+ times with the
|
161
|
+
# declared argument list. This may be modified by the +at_least+
|
162
|
+
# and +at_most+ declarators.
|
163
|
+
def times(limit)
|
164
|
+
@count_validators << @count_validator_class.new(self, limit) unless limit.nil?
|
165
|
+
@count_validator_class = ExactCountValidator
|
166
|
+
self
|
167
|
+
end
|
168
|
+
|
169
|
+
# Declare that the method is never expected to be called with the
|
170
|
+
# given argument list. This may be modified by the +at_least+ and
|
171
|
+
# +at_most+ declarators.
|
172
|
+
def never
|
173
|
+
times(0)
|
174
|
+
end
|
175
|
+
|
176
|
+
# Declare that the method is expected to be called exactly once
|
177
|
+
# with the given argument list. This may be modified by the
|
178
|
+
# +at_least+ and +at_most+ declarators.
|
179
|
+
def once
|
180
|
+
times(1)
|
181
|
+
end
|
182
|
+
|
183
|
+
# Declare that the method is expected to be called exactly twice
|
184
|
+
# with the given argument list. This may be modified by the
|
185
|
+
# +at_least+ and +at_most+ declarators.
|
186
|
+
def twice
|
187
|
+
times(2)
|
188
|
+
end
|
189
|
+
|
190
|
+
# Modifies the next call count declarator (+times+, +never+,
|
191
|
+
# +once+ or +twice+) so that the declarator means the method is
|
192
|
+
# called at least that many times.
|
193
|
+
#
|
194
|
+
# E.g. method f must be called at least twice:
|
195
|
+
#
|
196
|
+
# mock.should_receive(:f).at_least.twice
|
197
|
+
#
|
198
|
+
def at_least
|
199
|
+
@count_validator_class = AtLeastCountValidator
|
200
|
+
self
|
201
|
+
end
|
202
|
+
|
203
|
+
# Modifies the next call count declarator (+times+, +never+,
|
204
|
+
# +once+ or +twice+) so that the declarator means the method is
|
205
|
+
# called at most that many times.
|
206
|
+
#
|
207
|
+
# E.g. method f must be called no more than twice
|
208
|
+
#
|
209
|
+
# mock.should_receive(:f).at_most.twice
|
210
|
+
#
|
211
|
+
def at_most
|
212
|
+
@count_validator_class = AtMostCountValidator
|
213
|
+
self
|
214
|
+
end
|
215
|
+
|
216
|
+
# Declare that the given method must be called in order. All
|
217
|
+
# ordered method calls must be received in the order specified by
|
218
|
+
# the ordering of the +should_receive+ messages. Receiving a
|
219
|
+
# methods out of the specified order will cause a test failure.
|
220
|
+
#
|
221
|
+
# If the user needs more fine control over ordering
|
222
|
+
# (e.g. specifying that a group of messages may be received in any
|
223
|
+
# order as long as they all come after another group of messages),
|
224
|
+
# a _group_ _name_ may be specified in the +ordered+ calls. All
|
225
|
+
# messages within the same group may be received in any order.
|
226
|
+
#
|
227
|
+
# For example, in the following, messages +flip+ and +flop+ may be
|
228
|
+
# received in any order (because they are in the same group), but
|
229
|
+
# must occur strictly after +start+ but before +end+. The message
|
230
|
+
# +any_time+ may be received at any time because it is not
|
231
|
+
# ordered.
|
232
|
+
#
|
233
|
+
# m = FlexMock.new
|
234
|
+
# m.should_receive(:any_time)
|
235
|
+
# m.should_receive(:start).ordered
|
236
|
+
# m.should_receive(:flip).ordered(:flip_flop_group)
|
237
|
+
# m.should_receive(:flop).ordered(:flip_flop_group)
|
238
|
+
# m.should_receive(:end).ordered
|
239
|
+
#
|
240
|
+
def ordered(group_name=nil)
|
241
|
+
if group_name.nil?
|
242
|
+
@order_number = @mock.mock_allocate_order
|
243
|
+
elsif (num = @mock.mock_groups[group_name])
|
244
|
+
@order_number = num
|
245
|
+
else
|
246
|
+
@order_number = @mock.mock_allocate_order
|
247
|
+
@mock.mock_groups[group_name] = @order_number
|
248
|
+
end
|
249
|
+
self
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
##########################################################################
|
254
|
+
# A composite expectation allows several expectations to be grouped into a
|
255
|
+
# single composite and then apply the same constraints to all expectations
|
256
|
+
# in the group.
|
257
|
+
class CompositeExpectation
|
258
|
+
|
259
|
+
# Initialize the composite expectation.
|
260
|
+
def initialize
|
261
|
+
@expectations = []
|
262
|
+
end
|
263
|
+
|
264
|
+
# Add an expectation to the composite.
|
265
|
+
def add(expectation)
|
266
|
+
@expectations << expectation
|
267
|
+
end
|
268
|
+
|
269
|
+
# Apply the constraint method to all expectations in the composite.
|
270
|
+
def method_missing(sym, *args, &block)
|
271
|
+
@expectations.each do |expectation|
|
272
|
+
expectation.send(sym, *args, &block)
|
273
|
+
end
|
274
|
+
self
|
275
|
+
end
|
276
|
+
|
277
|
+
# The following methods return a value, so we make an arbitrary choice
|
278
|
+
# and return the value for the first expectation in the composite.
|
279
|
+
|
280
|
+
# Return the order number of the first expectation in the list.
|
281
|
+
def order_number
|
282
|
+
@expectations.first.order_number
|
283
|
+
end
|
284
|
+
|
285
|
+
# Return the associated mock object.
|
286
|
+
def mock
|
287
|
+
@expectations.first.mock
|
288
|
+
end
|
289
|
+
|
290
|
+
# Start a new method expectation. The following constraints will be
|
291
|
+
# applied to the new expectation.
|
292
|
+
def should_receive(*args, &block)
|
293
|
+
@expectations.first.mock.should_receive(*args, &block)
|
294
|
+
end
|
295
|
+
|
296
|
+
# Return a string representations
|
297
|
+
def to_s
|
298
|
+
if @expectations.size > 1
|
299
|
+
"[" + @expectations.collect { |e| e.to_s }.join(', ') + "]"
|
300
|
+
else
|
301
|
+
@expectations.first.to_s
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
##########################################################################
|
307
|
+
# An expectation recorder records any expectations received and plays them
|
308
|
+
# back on demand. This is used to collect the expectations in the blockless
|
309
|
+
# version of the new_instances call.
|
310
|
+
#
|
311
|
+
class ExpectationRecorder
|
312
|
+
|
313
|
+
# Initialize the recorder.
|
314
|
+
def initialize
|
315
|
+
@expectations = []
|
316
|
+
end
|
317
|
+
|
318
|
+
# Save any incoming messages to be played back later.
|
319
|
+
def method_missing(sym, *args, &block)
|
320
|
+
@expectations << [sym, args, block]
|
321
|
+
self
|
322
|
+
end
|
323
|
+
|
324
|
+
# Apply the recorded messages to the given object in a chaining fashion
|
325
|
+
# (i.e. the result of the previous call is used as the target of the next
|
326
|
+
# call).
|
327
|
+
def apply(mock)
|
328
|
+
obj = mock
|
329
|
+
@expectations.each do |sym, args, block|
|
330
|
+
obj = obj.send(sym, *args, &block)
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#---
|
4
|
+
# Copyright 2003, 2004, 2005, 2006, 2007 by Jim Weirich (jim@weirichhouse.org).
|
5
|
+
# All rights reserved.
|
6
|
+
|
7
|
+
# Permission is granted for use, copying, modification, distribution,
|
8
|
+
# and distribution of modified versions of this work as long as the
|
9
|
+
# above copyright notice is included.
|
10
|
+
#+++
|
11
|
+
|
12
|
+
require 'flexmock/noop'
|
13
|
+
|
14
|
+
class FlexMock
|
15
|
+
|
16
|
+
####################################################################
|
17
|
+
# The expectation director is responsible for routing calls to the
|
18
|
+
# correct expectations for a given argument list.
|
19
|
+
#
|
20
|
+
class ExpectationDirector
|
21
|
+
|
22
|
+
# Create an ExpectationDirector for a mock object.
|
23
|
+
def initialize(sym)
|
24
|
+
@sym = sym
|
25
|
+
@expectations = []
|
26
|
+
@expected_order = nil
|
27
|
+
end
|
28
|
+
|
29
|
+
# Invoke the expectations for a given set of arguments.
|
30
|
+
#
|
31
|
+
# First, look for an expectation that matches the arguements and
|
32
|
+
# is eligible to be called. Failing that, look for a expectation
|
33
|
+
# that matches the arguments (at this point it will be ineligible,
|
34
|
+
# but at least we will get a good failure message). Finally,
|
35
|
+
# check for expectations that don't have any argument matching
|
36
|
+
# criteria.
|
37
|
+
def call(*args)
|
38
|
+
exp = @expectations.find { |e| e.match_args(args) && e.eligible? } ||
|
39
|
+
@expectations.find { |e| e.match_args(args) }
|
40
|
+
FlexMock.check("no matching handler found for " +
|
41
|
+
FlexMock.format_args(@sym, args)) { ! exp.nil? }
|
42
|
+
exp.verify_call(*args)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Append an expectation to this director.
|
46
|
+
def <<(expectation)
|
47
|
+
@expectations << expectation
|
48
|
+
end
|
49
|
+
|
50
|
+
# Do the post test verification for this directory. Check all the
|
51
|
+
# expectations.
|
52
|
+
def mock_verify
|
53
|
+
@expectations.each do |exp|
|
54
|
+
exp.mock_verify
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#---
|
4
|
+
# Copyright 2003, 2004, 2005, 2006, 2007 by Jim Weirich (jim@weirichhouse.org).
|
5
|
+
# All rights reserved.
|
6
|
+
|
7
|
+
# Permission is granted for use, copying, modification, distribution,
|
8
|
+
# and distribution of modified versions of this work as long as the
|
9
|
+
# above copyright notice is included.
|
10
|
+
#+++
|
11
|
+
|
12
|
+
require 'flexmock/noop'
|
13
|
+
|
14
|
+
class FlexMock
|
15
|
+
|
16
|
+
####################################################################
|
17
|
+
# Mock container methods
|
18
|
+
#
|
19
|
+
# Include this module in to get integration with FlexMock. When
|
20
|
+
# this module is included, mocks may be created with a simple call
|
21
|
+
# to the +flexmock+ method. Mocks created with via the method call
|
22
|
+
# will automatically be verified in the teardown of the test case.
|
23
|
+
#
|
24
|
+
module MockContainer
|
25
|
+
# Do the flexmock specific teardown stuff. If you need finer control,
|
26
|
+
# you can use either +flexmock_verify+ or +flexmock_close+.
|
27
|
+
def flexmock_teardown
|
28
|
+
flexmock_verify if passed?
|
29
|
+
ensure
|
30
|
+
flexmock_close
|
31
|
+
end
|
32
|
+
|
33
|
+
# Perform verification on all mocks in the container.
|
34
|
+
def flexmock_verify
|
35
|
+
@flexmock_created_mocks ||= []
|
36
|
+
@flexmock_created_mocks.each do |m|
|
37
|
+
m.mock_verify
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Close all the mock objects in the container. Closing a mock object
|
42
|
+
# restores any original behavior that was displaced by the mock.
|
43
|
+
def flexmock_close
|
44
|
+
@flexmock_created_mocks ||= []
|
45
|
+
@flexmock_created_mocks.each do |m|
|
46
|
+
m.mock_teardown
|
47
|
+
end
|
48
|
+
@flexmock_created_mocks = []
|
49
|
+
end
|
50
|
+
|
51
|
+
# Create a mocking object in the FlexMock framework. The +flexmock+
|
52
|
+
# method has a number of options available, depending on just what
|
53
|
+
# kind of mocking object your require. Mocks created via +flexmock+
|
54
|
+
# will be automatically verify during the teardown phase of your
|
55
|
+
# test framework.
|
56
|
+
#
|
57
|
+
# :call-seq:
|
58
|
+
# flexmock() { |mock| ... }
|
59
|
+
# flexmock(name) { |mock| ... }
|
60
|
+
# flexmock(expect_hash) { |mock| ... }
|
61
|
+
# flexmock(name, expect_hash) { |mock| ... }
|
62
|
+
# flexmock(real_object) { |mock| ... }
|
63
|
+
# flexmock(real_object, name) { |mock| ... }
|
64
|
+
# flexmock(real_object, name, expect_hash) { |mock| ... }
|
65
|
+
# flexmock(:base, string, name, expect_hash) { |mock| ... }
|
66
|
+
#
|
67
|
+
# name ::
|
68
|
+
# Name of the mock object. If no name is given, "unknown" is used for
|
69
|
+
# full mocks and "flexmock(<em>real_object</em>)" is used for partial
|
70
|
+
# mocks.
|
71
|
+
#
|
72
|
+
# expect_hash ::
|
73
|
+
# Hash table of method names and values. Each method/value pair is
|
74
|
+
# used to setup a simple expectation so that if the mock object
|
75
|
+
# receives a message matching an entry in the table, it returns
|
76
|
+
# the associated value. No argument our call count constraints are
|
77
|
+
# added. Using an expect_hash is identical to calling:
|
78
|
+
#
|
79
|
+
# mock.should_receive(method_name).and_return(value)
|
80
|
+
#
|
81
|
+
# for each of the method/value pairs in the hash.
|
82
|
+
#
|
83
|
+
# real_object ::
|
84
|
+
# If a real object is given, then a partial mock is constructed
|
85
|
+
# using the real_object as a base. Partial mocks (formally referred
|
86
|
+
# to as stubs) behave as a mock object when an expectation is matched,
|
87
|
+
# and otherwise will behave like the original object. This is useful
|
88
|
+
# when you want to use a real object for testing, but need to mock out
|
89
|
+
# just one or two methods.
|
90
|
+
#
|
91
|
+
# :base ::
|
92
|
+
# Forces the following argument to be used as the base of a
|
93
|
+
# partial mock object. This explicit tag is only needed if you
|
94
|
+
# want to use a string or a symbol as the mock base (string and
|
95
|
+
# symbols would normally be interpretted as the mock name).
|
96
|
+
#
|
97
|
+
# &block ::
|
98
|
+
# If a block is given, then the mock object is passed to the block and
|
99
|
+
# expectations may be configured within the block.
|
100
|
+
#
|
101
|
+
def flexmock(*args)
|
102
|
+
name = nil
|
103
|
+
quick_defs = {}
|
104
|
+
stub_target = nil
|
105
|
+
while ! args.empty?
|
106
|
+
case args.first
|
107
|
+
when :base
|
108
|
+
args.shift
|
109
|
+
stub_target = args.shift
|
110
|
+
when String, Symbol
|
111
|
+
name = args.shift.to_s
|
112
|
+
when Hash
|
113
|
+
quick_defs = args.shift
|
114
|
+
else
|
115
|
+
stub_target = args.shift
|
116
|
+
end
|
117
|
+
end
|
118
|
+
if stub_target
|
119
|
+
mock = flexmock_make_stub(stub_target, name)
|
120
|
+
else
|
121
|
+
mock = FlexMock.new(name || "unknown")
|
122
|
+
end
|
123
|
+
flexmock_quick_define(mock, quick_defs)
|
124
|
+
yield(mock) if block_given?
|
125
|
+
flexmock_remember(mock)
|
126
|
+
mock
|
127
|
+
end
|
128
|
+
alias flexstub flexmock
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
# Create a PartialMock for the given object. Use +name+ as the name
|
133
|
+
# of the mock object.
|
134
|
+
def flexmock_make_stub(obj, name)
|
135
|
+
name ||= "flexmock(#{obj.class.to_s})"
|
136
|
+
obj.instance_eval {
|
137
|
+
@flexmock_proxy ||= PartialMock.new(obj, FlexMock.new(name))
|
138
|
+
}
|
139
|
+
obj.instance_variable_get("@flexmock_proxy")
|
140
|
+
end
|
141
|
+
|
142
|
+
# Create a set of mocked methods from a hash.
|
143
|
+
def flexmock_quick_define(mock, defs)
|
144
|
+
defs.each do |method, value|
|
145
|
+
mock.should_receive(method).and_return(value)
|
146
|
+
end
|
147
|
+
mock
|
148
|
+
end
|
149
|
+
|
150
|
+
# Remember the mock object / stub in the mock container.
|
151
|
+
def flexmock_remember(mocking_object)
|
152
|
+
@flexmock_created_mocks ||= []
|
153
|
+
@flexmock_created_mocks << mocking_object
|
154
|
+
mocking_object.mock_container = self
|
155
|
+
mocking_object
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|