flexmock 2.3.0 → 2.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/flexmock/core.rb +44 -13
- data/lib/flexmock/expectation.rb +0 -5
- data/lib/flexmock/expectation_builder.rb +1 -1
- data/lib/flexmock/mock_container.rb +2 -1
- data/lib/flexmock/partial_mock.rb +84 -23
- data/lib/flexmock/validators.rb +44 -12
- data/lib/flexmock/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 16f8df99b548903abdd25fef26a98df2906448bf
|
4
|
+
data.tar.gz: 7ce30d1e5ada1a4d679e53db575bd3d942b8e836
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7ff6a1a9172b9df71a8d5d3c8717304cad88d7947ea212c45417f53106001b71587879bfcd9684301440fc766db0a48552f5fc80b81dbd55e4d65c81acc55a23
|
7
|
+
data.tar.gz: e93acaa91ace46df1fd14ead3c4790b857a654fb901d6a4d08193eae607abf65eeefa78e199b5e034855c72752d5b7bb824aa2d88455b229c740842dc2e8871a
|
data/lib/flexmock/core.rb
CHANGED
@@ -45,7 +45,7 @@ class FlexMock
|
|
45
45
|
include Ordering
|
46
46
|
|
47
47
|
attr_reader :flexmock_name
|
48
|
-
|
48
|
+
attr_reader :flexmock_container_stack
|
49
49
|
|
50
50
|
class << self
|
51
51
|
attr_accessor :partials_are_based
|
@@ -54,21 +54,50 @@ class FlexMock
|
|
54
54
|
self.partials_are_based = false
|
55
55
|
self.partials_verify_signatures = false
|
56
56
|
|
57
|
+
# Null object for {#parent_mock}
|
58
|
+
class NullParentMock
|
59
|
+
def flexmock_expectations_for(sym)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
57
63
|
# Create a FlexMock object with the given name. The name is used in
|
58
64
|
# error messages. If no container is given, create a new, one-off
|
59
65
|
# container for this mock.
|
60
|
-
def initialize(name="unknown", container=nil)
|
66
|
+
def initialize(name="unknown", container=nil, parent: nil)
|
61
67
|
@flexmock_name = name
|
62
68
|
@flexmock_closed = false
|
69
|
+
@flexmock_container_stack = Array.new
|
63
70
|
@expectations = Hash.new
|
64
|
-
@ignore_missing = false
|
65
71
|
@verified = false
|
66
72
|
@calls = []
|
67
73
|
@base_class = nil
|
74
|
+
if parent
|
75
|
+
@ignore_missing = parent.ignore_missing?
|
76
|
+
@parent_mock = parent
|
77
|
+
else
|
78
|
+
@ignore_missing = false
|
79
|
+
@parent_mock = NullParentMock.new
|
80
|
+
end
|
68
81
|
container = UseContainer.new if container.nil?
|
69
82
|
container.flexmock_remember(self)
|
70
83
|
end
|
71
84
|
|
85
|
+
def ignore_missing?
|
86
|
+
@ignore_missing
|
87
|
+
end
|
88
|
+
|
89
|
+
def flexmock_container
|
90
|
+
flexmock_container_stack.last
|
91
|
+
end
|
92
|
+
|
93
|
+
def push_flexmock_container(container)
|
94
|
+
flexmock_container_stack.push(container)
|
95
|
+
end
|
96
|
+
|
97
|
+
def pop_flexmock_container
|
98
|
+
flexmock_container_stack.pop
|
99
|
+
end
|
100
|
+
|
72
101
|
# Return the inspection string for a mock.
|
73
102
|
def inspect
|
74
103
|
"<FlexMock:#{flexmock_name}>"
|
@@ -117,8 +146,8 @@ class FlexMock
|
|
117
146
|
flexmock_wrap do
|
118
147
|
if flexmock_closed?
|
119
148
|
FlexMock.undefined
|
120
|
-
elsif
|
121
|
-
|
149
|
+
elsif exp = flexmock_expectations_for(sym)
|
150
|
+
exp.call(enhanced_args, call_record)
|
122
151
|
elsif @base_class && @base_class.flexmock_defined?(sym)
|
123
152
|
FlexMock.undefined
|
124
153
|
elsif @ignore_missing
|
@@ -139,13 +168,14 @@ class FlexMock
|
|
139
168
|
|
140
169
|
# Find the mock expectation for method sym and arguments.
|
141
170
|
def flexmock_find_expectation(method_name, *args) # :nodoc:
|
142
|
-
exp =
|
143
|
-
|
171
|
+
if exp = flexmock_expectations_for(method_name)
|
172
|
+
exp.find_expectation(*args)
|
173
|
+
end
|
144
174
|
end
|
145
175
|
|
146
176
|
# Return the expectation director for a method name.
|
147
177
|
def flexmock_expectations_for(method_name) # :nodoc:
|
148
|
-
@expectations[method_name]
|
178
|
+
@expectations[method_name] || @parent_mock.flexmock_expectations_for(method_name)
|
149
179
|
end
|
150
180
|
|
151
181
|
def flexmock_base_class
|
@@ -183,9 +213,9 @@ class FlexMock
|
|
183
213
|
|
184
214
|
# Override the built-in +method+ to include the mocked methods.
|
185
215
|
def method(method_name)
|
186
|
-
|
216
|
+
flexmock_expectations_for(method_name) || super
|
187
217
|
rescue NameError => ex
|
188
|
-
if
|
218
|
+
if ignore_missing?
|
189
219
|
proc { FlexMock.undefined }
|
190
220
|
else
|
191
221
|
raise ex
|
@@ -218,10 +248,11 @@ class FlexMock
|
|
218
248
|
# Using +location+, define the expectations specified by +args+.
|
219
249
|
def flexmock_define_expectation(location, *args)
|
220
250
|
@last_expectation = EXP_BUILDER.parse_should_args(self, args) do |method_name|
|
221
|
-
|
251
|
+
exp = flexmock_expectations_for(method_name) || ExpectationDirector.new(method_name)
|
252
|
+
@expectations[method_name] = exp
|
222
253
|
result = Expectation.new(self, method_name, location)
|
223
|
-
|
224
|
-
override_existing_method(method_name) if flexmock_respond_to?(method_name)
|
254
|
+
exp << result
|
255
|
+
override_existing_method(method_name) if flexmock_respond_to?(method_name, true)
|
225
256
|
result = ExplicitNeeded.new(result, method_name, @base_class) if
|
226
257
|
@base_class && ! @base_class.flexmock_defined?(method_name)
|
227
258
|
result
|
data/lib/flexmock/expectation.rb
CHANGED
@@ -143,11 +143,6 @@ class FlexMock
|
|
143
143
|
@count_validators.all? { |v| v.eligible?(@actual_count) }
|
144
144
|
end
|
145
145
|
|
146
|
-
# Is this expectation constrained by any call counts?
|
147
|
-
def call_count_constrained?
|
148
|
-
! @count_validators.empty?
|
149
|
-
end
|
150
|
-
|
151
146
|
# Validate that the order
|
152
147
|
def validate_order
|
153
148
|
if @order_number
|
@@ -52,6 +52,7 @@ class FlexMock
|
|
52
52
|
def flexmock_close
|
53
53
|
flexmock_created_mocks.each do |m|
|
54
54
|
m.flexmock_teardown
|
55
|
+
m.pop_flexmock_container
|
55
56
|
end
|
56
57
|
@flexmock_created_mocks = []
|
57
58
|
end
|
@@ -127,7 +128,7 @@ class FlexMock
|
|
127
128
|
def flexmock_remember(mocking_object)
|
128
129
|
@flexmock_created_mocks ||= []
|
129
130
|
@flexmock_created_mocks << mocking_object
|
130
|
-
mocking_object.
|
131
|
+
mocking_object.push_flexmock_container(self)
|
131
132
|
mocking_object
|
132
133
|
end
|
133
134
|
|
@@ -28,27 +28,64 @@ class FlexMock
|
|
28
28
|
|
29
29
|
attr_reader :mock
|
30
30
|
|
31
|
-
|
31
|
+
# Boxing of the flexmock proxy
|
32
|
+
#
|
33
|
+
# It is managed as a stack in order to allow to setup containers recursively
|
34
|
+
# (as e.g. FlexMock.use( ... ) checks)
|
35
|
+
class ProxyBox
|
36
|
+
attr_reader :stack
|
37
|
+
|
38
|
+
Element = Struct.new :proxy, :container
|
39
|
+
|
40
|
+
def initialize
|
41
|
+
@stack = [Element.new]
|
42
|
+
end
|
43
|
+
|
44
|
+
# Tests whether the given container is the one on which the current proxy
|
45
|
+
# acts
|
46
|
+
def container
|
47
|
+
stack.last.container
|
48
|
+
end
|
49
|
+
|
50
|
+
def proxy
|
51
|
+
stack.last.proxy
|
52
|
+
end
|
53
|
+
|
54
|
+
def push(proxy, container)
|
55
|
+
stack.push(Element.new(proxy, container))
|
56
|
+
end
|
57
|
+
|
58
|
+
def pop
|
59
|
+
if !stack.empty?
|
60
|
+
stack.pop
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def empty?
|
65
|
+
stack.size == 1
|
66
|
+
end
|
67
|
+
end
|
32
68
|
|
33
69
|
# Make a partial mock proxy and install it on the target +obj+.
|
34
70
|
def self.make_proxy_for(obj, container, name, safe_mode)
|
35
71
|
name ||= "flexmock(#{obj.class.to_s})"
|
36
|
-
if !
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
obj.instance_variable_get("@flexmock_proxy").proxy = proxy
|
41
|
-
else
|
42
|
-
obj.instance_variable_set("@flexmock_proxy", ProxyBox.new(proxy))
|
43
|
-
end
|
72
|
+
if !obj.instance_variable_defined?("@flexmock_proxy")
|
73
|
+
proxy_box = obj.instance_variable_set("@flexmock_proxy", ProxyBox.new)
|
74
|
+
else
|
75
|
+
proxy_box = obj.instance_variable_get("@flexmock_proxy")
|
44
76
|
end
|
45
|
-
obj.instance_variable_get("@flexmock_proxy").proxy
|
46
|
-
end
|
47
77
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
78
|
+
if proxy_box.container != container
|
79
|
+
if !proxy_box.empty?
|
80
|
+
parent_proxy, _ = proxy_box.proxy
|
81
|
+
parent_mock = parent_proxy.mock
|
82
|
+
end
|
83
|
+
|
84
|
+
mock = FlexMock.new(name, container, parent: parent_mock)
|
85
|
+
proxy = PartialMockProxy.new(obj, mock, safe_mode, parent: parent_proxy)
|
86
|
+
proxy_box.push(proxy, container)
|
87
|
+
end
|
88
|
+
proxy_box.proxy
|
52
89
|
end
|
53
90
|
|
54
91
|
# The following methods are added to partial mocks so that they
|
@@ -62,14 +99,21 @@ class FlexMock
|
|
62
99
|
:invoke_original
|
63
100
|
]
|
64
101
|
|
102
|
+
attr_reader :method_definitions
|
103
|
+
|
65
104
|
# Initialize a PartialMockProxy object.
|
66
|
-
def initialize(obj, mock, safe_mode)
|
105
|
+
def initialize(obj, mock, safe_mode, parent: nil)
|
67
106
|
@obj = obj
|
68
107
|
@mock = mock
|
69
|
-
@method_definitions = {}
|
70
|
-
@methods_proxied = []
|
71
108
|
@proxy_definition_module = nil
|
72
109
|
@initialize_override = nil
|
110
|
+
|
111
|
+
if parent
|
112
|
+
@method_definitions = parent.method_definitions.dup
|
113
|
+
else
|
114
|
+
@method_definitions = {}
|
115
|
+
end
|
116
|
+
|
73
117
|
unless safe_mode
|
74
118
|
add_mock_method(:should_receive)
|
75
119
|
MOCK_METHODS.each do |sym|
|
@@ -85,6 +129,14 @@ class FlexMock
|
|
85
129
|
@mock
|
86
130
|
end
|
87
131
|
|
132
|
+
def push_flexmock_container(container)
|
133
|
+
@mock.push_flexmock_container(container)
|
134
|
+
end
|
135
|
+
|
136
|
+
def pop_flexmock_container
|
137
|
+
@mock.pop_flexmock_container
|
138
|
+
end
|
139
|
+
|
88
140
|
# :call-seq:
|
89
141
|
# should_receive(:method_name)
|
90
142
|
# should_receive(:method1, method2, ...)
|
@@ -119,9 +171,20 @@ class FlexMock
|
|
119
171
|
flexmock_invoke_original(m, args)
|
120
172
|
end
|
121
173
|
|
174
|
+
# Whether the given method's original definition has been stored
|
175
|
+
def has_original_method?(m)
|
176
|
+
@method_definitions.has_key?(m)
|
177
|
+
end
|
178
|
+
|
179
|
+
# Whether the given method is already being proxied
|
180
|
+
def has_proxied_method?(m)
|
181
|
+
@proxy_definition_module &&
|
182
|
+
@proxy_definition_module.method_defined?(m)
|
183
|
+
end
|
184
|
+
|
122
185
|
def flexmock_define_expectation(location, *args)
|
123
186
|
EXP_BUILDER.parse_should_args(self, args) do |method_name|
|
124
|
-
if
|
187
|
+
if !has_proxied_method?(method_name) && !has_original_method?(method_name)
|
125
188
|
hide_existing_method(method_name)
|
126
189
|
end
|
127
190
|
ex = @mock.flexmock_define_expectation(location, method_name)
|
@@ -278,7 +341,7 @@ class FlexMock
|
|
278
341
|
end
|
279
342
|
if @obj.instance_variable_defined?(:@flexmock_proxy) &&
|
280
343
|
(box = @obj.instance_variable_get(:@flexmock_proxy))
|
281
|
-
box.
|
344
|
+
box.pop
|
282
345
|
end
|
283
346
|
@obj = nil
|
284
347
|
end
|
@@ -358,9 +421,8 @@ class FlexMock
|
|
358
421
|
# Stow the existing method definition so that it can be recovered
|
359
422
|
# later.
|
360
423
|
def stow_existing_definition(method_name)
|
361
|
-
if !@
|
424
|
+
if !@method_definitions.has_key?(method_name)
|
362
425
|
@method_definitions[method_name] = target_class_eval { instance_method(method_name) }
|
363
|
-
@methods_proxied << method_name
|
364
426
|
end
|
365
427
|
@method_definitions[method_name]
|
366
428
|
rescue NameError
|
@@ -390,6 +452,5 @@ class FlexMock
|
|
390
452
|
def detached?
|
391
453
|
@obj.nil?
|
392
454
|
end
|
393
|
-
|
394
455
|
end
|
395
456
|
end
|
data/lib/flexmock/validators.rb
CHANGED
@@ -213,18 +213,28 @@ class FlexMock
|
|
213
213
|
# @param [Array] args
|
214
214
|
# @raise ValidationFailed
|
215
215
|
def validate(args)
|
216
|
+
args = args.dup
|
216
217
|
kw_args = Hash.new
|
218
|
+
|
219
|
+
last_is_proc = false
|
220
|
+
begin
|
221
|
+
if args.last.kind_of?(Proc)
|
222
|
+
args.pop
|
223
|
+
last_is_proc = true
|
224
|
+
end
|
225
|
+
rescue NoMethodError
|
226
|
+
end
|
227
|
+
|
228
|
+
last_is_kw_hash = false
|
217
229
|
if expects_keyword_arguments?
|
218
230
|
last_is_kw_hash =
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
end
|
231
|
+
begin
|
232
|
+
args.last.kind_of?(Hash)
|
233
|
+
rescue NoMethodError
|
234
|
+
end
|
224
235
|
|
225
236
|
if last_is_kw_hash
|
226
|
-
kw_args = args
|
227
|
-
args = args[0..-2]
|
237
|
+
kw_args = args.pop
|
228
238
|
elsif requires_keyword_arguments?
|
229
239
|
raise ValidationFailed, "#{@exp} expects keyword arguments but none were provided"
|
230
240
|
end
|
@@ -232,12 +242,34 @@ class FlexMock
|
|
232
242
|
|
233
243
|
# There is currently no way to disambiguate "given a block" from "given a
|
234
244
|
# proc as last argument" ... give some leeway in this case
|
245
|
+
positional_count = args.size
|
246
|
+
|
247
|
+
if required_arguments > positional_count
|
248
|
+
if requires_keyword_arguments?
|
249
|
+
raise ValidationFailed, "#{@exp} expects at least #{required_arguments} positional arguments but got only #{positional_count}"
|
250
|
+
end
|
251
|
+
|
252
|
+
if (required_arguments - positional_count) == 1 && (last_is_kw_hash || last_is_proc)
|
253
|
+
if last_is_kw_hash
|
254
|
+
last_is_kw_hash = false
|
255
|
+
kw_args = Hash.new
|
256
|
+
else
|
257
|
+
last_is_proc = false
|
258
|
+
end
|
259
|
+
positional_count += 1
|
260
|
+
elsif (required_arguments - positional_count) == 2 && (last_is_kw_hash && last_is_proc)
|
261
|
+
last_is_kw_hash = false
|
262
|
+
kw_args = Hash.new
|
263
|
+
last_is_proc = false
|
264
|
+
positional_count += 2
|
265
|
+
else
|
266
|
+
raise ValidationFailed, "#{@exp} expects at least #{required_arguments} positional arguments but got only #{positional_count}"
|
267
|
+
end
|
268
|
+
end
|
235
269
|
|
236
|
-
if required_arguments
|
237
|
-
|
238
|
-
|
239
|
-
if !args.last.kind_of?(Proc) || (required_arguments + optional_arguments) < args.size - 1
|
240
|
-
raise ValidationFailed, "#{@exp} expects at most #{required_arguments + optional_arguments} positional arguments but got #{args.size}"
|
270
|
+
if !splat? && (required_arguments + optional_arguments) < positional_count
|
271
|
+
if !last_is_proc || (required_arguments + optional_arguments) < positional_count - 1
|
272
|
+
raise ValidationFailed, "#{@exp} expects at most #{required_arguments + optional_arguments} positional arguments but got #{positional_count}"
|
241
273
|
end
|
242
274
|
end
|
243
275
|
|
data/lib/flexmock/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flexmock
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.3.
|
4
|
+
version: 2.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jim Weirich
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-10-
|
12
|
+
date: 2016-10-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: minitest
|