flexmock 1.3.3 → 2.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.autotest +3 -0
- data/.gitignore +14 -0
- data/.togglerc +7 -0
- data/.travis.yml +5 -0
- data/.yardopts +2 -0
- data/CHANGES +11 -0
- data/Gemfile +1 -4
- data/README.md +39 -11
- data/Rakefile +6 -217
- data/doc/examples/rspec_examples_spec.rb +244 -0
- data/doc/examples/test_unit_examples_test.rb +240 -0
- data/doc/jamis.rb +591 -0
- data/flexmock.gemspec +33 -0
- data/lib/flexmock.rb +0 -1
- data/lib/flexmock/composite_expectation.rb +1 -1
- data/lib/flexmock/core.rb +3 -7
- data/lib/flexmock/core_class_methods.rb +5 -1
- data/lib/flexmock/default_framework_adapter.rb +2 -2
- data/lib/flexmock/expectation.rb +29 -3
- data/lib/flexmock/expectation_director.rb +1 -1
- data/lib/flexmock/minitest.rb +13 -0
- data/lib/flexmock/minitest_extensions.rb +26 -0
- data/lib/flexmock/minitest_integration.rb +111 -0
- data/lib/flexmock/mock_container.rb +1 -2
- data/lib/flexmock/partial_mock.rb +61 -104
- data/lib/flexmock/recorder.rb +1 -2
- data/lib/flexmock/rspec.rb +6 -3
- data/lib/flexmock/test_unit_integration.rb +14 -0
- data/lib/flexmock/validators.rb +5 -4
- data/lib/flexmock/version.rb +1 -9
- data/rakelib/metrics.rake +40 -0
- data/rakelib/preview.rake +4 -0
- data/rakelib/tags.rake +18 -0
- data/todo.txt +20 -0
- metadata +61 -86
- data/Gemfile.lock +0 -20
- data/doc/examples/rspec_examples_spec.rdoc +0 -245
- data/doc/examples/test_unit_examples_test.rdoc +0 -241
- data/test/aliasing_test.rb +0 -66
- data/test/assert_spy_called_test.rb +0 -119
- data/test/base_class_test.rb +0 -71
- data/test/based_partials_test.rb +0 -51
- data/test/container_methods_test.rb +0 -118
- data/test/default_framework_adapter_test.rb +0 -38
- data/test/demeter_mocking_test.rb +0 -191
- data/test/deprecated_methods_test.rb +0 -225
- data/test/examples_from_readme_test.rb +0 -157
- data/test/expectation_description_test.rb +0 -80
- data/test/extended_should_receive_test.rb +0 -69
- data/test/flexmodel_test.rb +0 -54
- data/test/mock_builder_test.rb +0 -68
- data/test/naming_test.rb +0 -84
- data/test/new_instances_test.rb +0 -215
- data/test/object_extensions_test.rb +0 -25
- data/test/partial_mock_test.rb +0 -458
- data/test/record_mode_test.rb +0 -158
- data/test/redirect_error.rb +0 -16
- data/test/rspec_integration/integration_spec.rb +0 -56
- data/test/rspec_integration/spy_example_spec.rb +0 -207
- data/test/samples_test.rb +0 -283
- data/test/should_ignore_missing_test.rb +0 -84
- data/test/should_receive_test.rb +0 -1155
- data/test/spys_test.rb +0 -215
- data/test/symbol_extensions_test.rb +0 -8
- data/test/test_class_extensions.rb +0 -34
- data/test/test_setup.rb +0 -92
- data/test/test_unit_integration/auto_test_unit_test.rb +0 -42
- data/test/test_unit_integration/minitest_teardown_test.rb +0 -14
- data/test/tu_integration_test.rb +0 -99
- data/test/undefined_test.rb +0 -87
data/flexmock.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require './lib/flexmock/version.rb'
|
2
|
+
spec = Gem::Specification.new do |s|
|
3
|
+
#### Basic information.
|
4
|
+
s.name = 'flexmock'
|
5
|
+
s.version = FlexMock::VERSION
|
6
|
+
s.summary = "Simple and Flexible Mock Objects for Testing"
|
7
|
+
s.description = %{
|
8
|
+
FlexMock is a extremely simple mock object class compatible
|
9
|
+
with the Minitest framework. Although the FlexMock's
|
10
|
+
interface is simple, it is very flexible.
|
11
|
+
}
|
12
|
+
|
13
|
+
s.required_ruby_version = ">= 2.0"
|
14
|
+
|
15
|
+
s.license = 'MIT'
|
16
|
+
|
17
|
+
#### Dependencies and requirements.
|
18
|
+
|
19
|
+
s.add_development_dependency 'minitest'
|
20
|
+
s.add_development_dependency 'rake'
|
21
|
+
|
22
|
+
#### Which files are to be included in this gem? Everything! (Except CVS directories.)
|
23
|
+
|
24
|
+
s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
25
|
+
s.require_paths = ['lib'] # Use these for libraries.]
|
26
|
+
|
27
|
+
#### Author and project details.
|
28
|
+
|
29
|
+
s.authors = ["Jim Weirich", "Sylvain Joyeux"]
|
30
|
+
s.email = "sylvain.joyeux@m4x.org"
|
31
|
+
s.homepage = "https://github.com/doudou/flexmock"
|
32
|
+
end
|
33
|
+
|
data/lib/flexmock.rb
CHANGED
@@ -40,7 +40,7 @@ class FlexMock
|
|
40
40
|
# applied to the new expectation.
|
41
41
|
def should_receive(*args, &block)
|
42
42
|
@expectations.first.mock.
|
43
|
-
flexmock_define_expectation(caller
|
43
|
+
flexmock_define_expectation(caller, *args, &block)
|
44
44
|
end
|
45
45
|
|
46
46
|
# Return a string representations
|
data/lib/flexmock/core.rb
CHANGED
@@ -191,8 +191,7 @@ class FlexMock
|
|
191
191
|
# See Expectation for a list of declarators that can be used.
|
192
192
|
#
|
193
193
|
def should_receive(*args)
|
194
|
-
|
195
|
-
flexmock_define_expectation(location, *args)
|
194
|
+
flexmock_define_expectation(caller, *args)
|
196
195
|
end
|
197
196
|
|
198
197
|
# Using +location+, define the expectations specified by +args+.
|
@@ -230,13 +229,10 @@ class FlexMock
|
|
230
229
|
# that the mock name is added to the error message .
|
231
230
|
def flexmock_wrap(&block)
|
232
231
|
yield
|
233
|
-
rescue FlexMock.framework_adapter.assertion_failed_error => ex
|
234
|
-
raise
|
235
|
-
"in mock '#{@flexmock_name}': #{ex.message}",
|
236
|
-
ex.backtrace
|
232
|
+
rescue FlexMock.framework_adapter.assertion_failed_error, FlexMock.framework_adapter.check_failed_error => ex
|
233
|
+
raise ex, "in mock '#{@flexmock_name}': #{ex.message}", ex.backtrace
|
237
234
|
end
|
238
235
|
|
239
|
-
|
240
236
|
# Override the existing definition of method +method_name+ in the
|
241
237
|
# mock. Most methods depend on the method_missing trick to be
|
242
238
|
# invoked. However, if the method already exists, it will not call
|
@@ -67,7 +67,11 @@ class FlexMock
|
|
67
67
|
# Check will assert the block returns true. If it doesn't, an
|
68
68
|
# assertion failure is triggered with the given message.
|
69
69
|
def check(msg, &block) # :nodoc:
|
70
|
-
FlexMock.framework_adapter.
|
70
|
+
if FlexMock.framework_adapter.respond_to?(:check)
|
71
|
+
FlexMock.framework_adapter.check(msg, &block)
|
72
|
+
else
|
73
|
+
FlexMock.framework_adapter.make_assertion(msg, &block)
|
74
|
+
end
|
71
75
|
end
|
72
76
|
|
73
77
|
end
|
data/lib/flexmock/expectation.rb
CHANGED
@@ -68,10 +68,22 @@ class FlexMock
|
|
68
68
|
result
|
69
69
|
end
|
70
70
|
|
71
|
+
# Validate that this expectation is eligible for an extra call
|
72
|
+
def validate_eligible
|
73
|
+
@count_validators.each do |v|
|
74
|
+
if !v.eligible?(@actual_count)
|
75
|
+
v.validate(@actual_count + 1)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
rescue CountValidator::ValidationFailed => e
|
79
|
+
FlexMock.framework_adapter.check(e.message) { false }
|
80
|
+
end
|
81
|
+
|
71
82
|
# Verify the current call with the given arguments matches the
|
72
83
|
# expectations recorded in this object.
|
73
84
|
def verify_call(*args)
|
74
85
|
validate_order
|
86
|
+
validate_eligible
|
75
87
|
@actual_count += 1
|
76
88
|
perform_yielding(args)
|
77
89
|
return_value(args)
|
@@ -140,6 +152,8 @@ class FlexMock
|
|
140
152
|
@count_validators.each do |v|
|
141
153
|
v.validate(@actual_count)
|
142
154
|
end
|
155
|
+
rescue CountValidator::ValidationFailed => e
|
156
|
+
FlexMock.framework_adapter.make_assertion(e.message, @location) { false }
|
143
157
|
end
|
144
158
|
|
145
159
|
# Does the argument list match this expectation's argument
|
@@ -278,7 +292,15 @@ class FlexMock
|
|
278
292
|
def pass_thru(&block)
|
279
293
|
block ||= lambda { |value| value }
|
280
294
|
and_return { |*args|
|
281
|
-
|
295
|
+
begin
|
296
|
+
block.call(@mock.flexmock_invoke_original(@sym, args))
|
297
|
+
rescue NoMethodError => e
|
298
|
+
if e.name == @sym
|
299
|
+
raise e, "#{e.message} while performing #pass_thru in expectation object #{self}"
|
300
|
+
else
|
301
|
+
raise
|
302
|
+
end
|
303
|
+
end
|
282
304
|
}
|
283
305
|
end
|
284
306
|
|
@@ -417,8 +439,12 @@ class FlexMock
|
|
417
439
|
def flexmock_location_filter
|
418
440
|
yield
|
419
441
|
rescue Exception => ex
|
420
|
-
|
421
|
-
|
442
|
+
bt = @location.dup
|
443
|
+
flexmock_dir = File.expand_path(File.dirname(__FILE__))
|
444
|
+
while bt.first.start_with?(flexmock_dir)
|
445
|
+
bt.shift
|
446
|
+
end
|
447
|
+
raise ex, ex.message, bt
|
422
448
|
end
|
423
449
|
|
424
450
|
end
|
@@ -40,7 +40,7 @@ class FlexMock
|
|
40
40
|
call_record.expectation = exp if call_record
|
41
41
|
FlexMock.check(
|
42
42
|
"no matching handler found for " +
|
43
|
-
FlexMock.format_call(@sym, args)) { !
|
43
|
+
FlexMock.format_call(@sym, args)) { !exp.nil? }
|
44
44
|
returned_value = exp.verify_call(*args)
|
45
45
|
returned_value
|
46
46
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#---
|
4
|
+
# Copyright 2003-2013 by Jim Weirich (jim.weirich@gmail.com).
|
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/minitest_integration'
|
13
|
+
require 'flexmock/minitest_extensions'
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#---
|
4
|
+
# Copyright 2003-2013 by Jim Weirich (jim.weirich@gmail.com).
|
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
|
+
begin
|
13
|
+
# Minitest 5.0+
|
14
|
+
require 'minitest/test'
|
15
|
+
class Minitest::Test
|
16
|
+
include FlexMock::Minitest
|
17
|
+
end
|
18
|
+
|
19
|
+
rescue LoadError
|
20
|
+
# Minitest < 5.0, as shipped with ruby at least up to 2.1
|
21
|
+
require 'minitest/unit'
|
22
|
+
class MiniTest::Unit::TestCase
|
23
|
+
include FlexMock::Minitest
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,111 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#---
|
4
|
+
# Copyright 2003-2013 by Jim Weirich (jim.weirich@gmail.com).
|
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
|
+
begin
|
13
|
+
require 'minitest/assertions'
|
14
|
+
rescue LoadError
|
15
|
+
require 'minitest/unit'
|
16
|
+
end
|
17
|
+
|
18
|
+
require 'flexmock/base'
|
19
|
+
require 'flexmock/test_unit_assert_spy_called'
|
20
|
+
|
21
|
+
class FlexMock
|
22
|
+
|
23
|
+
# Minitest::Test Integration.
|
24
|
+
#
|
25
|
+
# Include this module in any Test subclass (in test-style minitest) or or
|
26
|
+
# describe block (in spec-style minitest) to get integration with FlexMock.
|
27
|
+
# When this module is included, the mock container methods (e.g. flexmock(),
|
28
|
+
# flexstub()) will be available.
|
29
|
+
#
|
30
|
+
module Minitest
|
31
|
+
include ArgumentTypes
|
32
|
+
include MockContainer
|
33
|
+
include TestUnitAssertions
|
34
|
+
|
35
|
+
# Teardown the test case, verifying any mocks that might have been
|
36
|
+
# defined in this test case.
|
37
|
+
def before_teardown
|
38
|
+
super
|
39
|
+
@flexmock_teardown_failure = nil
|
40
|
+
if respond_to?(:capture_exceptions)
|
41
|
+
capture_exceptions do
|
42
|
+
flexmock_teardown
|
43
|
+
end
|
44
|
+
else
|
45
|
+
begin
|
46
|
+
flexmock_teardown
|
47
|
+
rescue Exception => e
|
48
|
+
@flexmock_teardown_failure = e
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def after_teardown
|
54
|
+
if @flexmock_teardown_failure
|
55
|
+
raise @flexmock_teardown_failure
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class CheckFailedError < RuntimeError; end
|
61
|
+
|
62
|
+
# Adapter for adapting FlexMock to the Test::Unit framework.
|
63
|
+
#
|
64
|
+
class MinitestFrameworkAdapter
|
65
|
+
if defined?(Minitest::Test)
|
66
|
+
include Minitest::Assertions
|
67
|
+
else
|
68
|
+
include MiniTest::Assertions
|
69
|
+
end
|
70
|
+
|
71
|
+
attr_accessor :assertions
|
72
|
+
|
73
|
+
def initialize
|
74
|
+
@assertions = 0
|
75
|
+
end
|
76
|
+
|
77
|
+
def filtered_backtrace
|
78
|
+
bt = caller
|
79
|
+
flexmock_dir = File.expand_path(File.dirname(__FILE__))
|
80
|
+
while bt.first.start_with?(flexmock_dir)
|
81
|
+
bt.shift
|
82
|
+
end
|
83
|
+
bt
|
84
|
+
end
|
85
|
+
|
86
|
+
def make_assertion(msg, backtrace = caller, &block)
|
87
|
+
assert(yield, msg)
|
88
|
+
rescue Exception => e
|
89
|
+
e.set_backtrace backtrace
|
90
|
+
raise e
|
91
|
+
end
|
92
|
+
|
93
|
+
def check(msg, &block)
|
94
|
+
unless yield
|
95
|
+
msg = msg.call if msg.is_a?(Proc)
|
96
|
+
raise CheckFailedError, msg, filtered_backtrace
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def assertion_failed_error
|
101
|
+
MiniTest::Assertion
|
102
|
+
end
|
103
|
+
|
104
|
+
def check_failed_error
|
105
|
+
CheckFailedError
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
@framework_adapter = MinitestFrameworkAdapter.new
|
110
|
+
end
|
111
|
+
|
@@ -118,9 +118,8 @@ class FlexMock
|
|
118
118
|
# the mock object.
|
119
119
|
#
|
120
120
|
def flexmock(*args, &block)
|
121
|
-
location = caller.first
|
122
121
|
@flexmock_worker ||= MockBuilder.new(self)
|
123
|
-
@flexmock_worker.define_a_mock(
|
122
|
+
@flexmock_worker.define_a_mock(caller, *args, &block)
|
124
123
|
end
|
125
124
|
alias flexstub flexmock
|
126
125
|
|
@@ -28,21 +28,27 @@ class FlexMock
|
|
28
28
|
|
29
29
|
attr_reader :mock
|
30
30
|
|
31
|
+
ProxyBox = Struct.new :proxy
|
32
|
+
|
31
33
|
# Make a partial mock proxy and install it on the target +obj+.
|
32
34
|
def self.make_proxy_for(obj, container, name, safe_mode)
|
33
35
|
name ||= "flexmock(#{obj.class.to_s})"
|
34
36
|
if ! proxy_defined_on?(obj)
|
35
37
|
mock = FlexMock.new(name, container)
|
36
38
|
proxy = PartialMockProxy.new(obj, mock, safe_mode)
|
37
|
-
obj.
|
39
|
+
if obj.instance_variable_defined?("@flexmock_proxy")
|
40
|
+
obj.instance_variable_get("@flexmock_proxy").proxy = proxy
|
41
|
+
else
|
42
|
+
obj.instance_variable_set("@flexmock_proxy", ProxyBox.new(proxy))
|
43
|
+
end
|
38
44
|
end
|
39
|
-
obj.instance_variable_get("@flexmock_proxy")
|
45
|
+
obj.instance_variable_get("@flexmock_proxy").proxy
|
40
46
|
end
|
41
47
|
|
42
48
|
# Is there a mock proxy defined on the domain object?
|
43
49
|
def self.proxy_defined_on?(obj)
|
44
50
|
obj.instance_variable_defined?("@flexmock_proxy") &&
|
45
|
-
obj.instance_variable_get("@flexmock_proxy")
|
51
|
+
obj.instance_variable_get("@flexmock_proxy").proxy
|
46
52
|
end
|
47
53
|
|
48
54
|
# The following methods are added to partial mocks so that they
|
@@ -61,6 +67,7 @@ class FlexMock
|
|
61
67
|
@mock = mock
|
62
68
|
@method_definitions = {}
|
63
69
|
@methods_proxied = []
|
70
|
+
@proxy_definition_module = nil
|
64
71
|
unless safe_mode
|
65
72
|
add_mock_method(:should_receive)
|
66
73
|
MOCK_METHODS.each do |sym|
|
@@ -97,8 +104,7 @@ class FlexMock
|
|
97
104
|
#
|
98
105
|
# See Expectation for a list of declarators that can be used.
|
99
106
|
def should_receive(*args)
|
100
|
-
|
101
|
-
flexmock_define_expectation(location, *args)
|
107
|
+
flexmock_define_expectation(caller, *args)
|
102
108
|
end
|
103
109
|
|
104
110
|
def flexmock_define_expectation(location, *args)
|
@@ -118,9 +124,9 @@ class FlexMock
|
|
118
124
|
|
119
125
|
def add_mock_method(method_name)
|
120
126
|
stow_existing_definition(method_name)
|
121
|
-
|
127
|
+
proxy_module_eval do
|
122
128
|
define_method(method_name) { |*args, &block|
|
123
|
-
proxy =
|
129
|
+
proxy = __flexmock_proxy or
|
124
130
|
fail "Missing FlexMock proxy " +
|
125
131
|
"(for method_name=#{method_name.inspect}, self=\#{self})"
|
126
132
|
proxy.send(method_name, *args, &block)
|
@@ -149,11 +155,10 @@ class FlexMock
|
|
149
155
|
def new_instances(*allocators, &block)
|
150
156
|
fail ArgumentError, "new_instances requires a Class to stub" unless
|
151
157
|
Class === @obj
|
152
|
-
location = caller
|
158
|
+
location = caller
|
153
159
|
allocators = [:new] if allocators.empty?
|
154
160
|
expectation_recorder = ExpectationRecorder.new
|
155
161
|
allocators.each do |allocate_method|
|
156
|
-
check_allocate_method(allocate_method)
|
157
162
|
flexmock_define_expectation(location, allocate_method).and_return { |*args|
|
158
163
|
create_new_mocked_object(
|
159
164
|
allocate_method, args, expectation_recorder, block)
|
@@ -181,8 +186,15 @@ class FlexMock
|
|
181
186
|
# Invoke the original definition of method on the object supported by
|
182
187
|
# the stub.
|
183
188
|
def flexmock_invoke_original(method, args)
|
184
|
-
|
185
|
-
|
189
|
+
if original_method = @method_definitions[method]
|
190
|
+
if Proc === args.last
|
191
|
+
block = args.last
|
192
|
+
args = args[0..-2]
|
193
|
+
end
|
194
|
+
original_method.bind(@obj).call(*args, &block)
|
195
|
+
else
|
196
|
+
@obj.__send__(:method_missing, method, *args, &block)
|
197
|
+
end
|
186
198
|
end
|
187
199
|
|
188
200
|
# Verify that the mock has been properly called. After verification,
|
@@ -194,11 +206,16 @@ class FlexMock
|
|
194
206
|
# Remove all traces of the mocking framework from the existing object.
|
195
207
|
def flexmock_teardown
|
196
208
|
if ! detached?
|
197
|
-
|
198
|
-
|
199
|
-
|
209
|
+
proxy_module_eval do
|
210
|
+
methods = instance_methods(false).to_a
|
211
|
+
methods.each do |m|
|
212
|
+
remove_method m
|
213
|
+
end
|
214
|
+
end
|
215
|
+
if @obj.instance_variable_defined?(:@flexmock_proxy) &&
|
216
|
+
(box = @obj.instance_variable_get(:@flexmock_proxy))
|
217
|
+
box.proxy = nil
|
200
218
|
end
|
201
|
-
@obj.instance_variable_set("@flexmock_proxy", nil)
|
202
219
|
@obj = nil
|
203
220
|
end
|
204
221
|
end
|
@@ -235,16 +252,9 @@ class FlexMock
|
|
235
252
|
|
236
253
|
private
|
237
254
|
|
238
|
-
def check_allocate_method(allocate_method)
|
239
|
-
if allocate_method == :allocate && RUBY_VERSION >= "1.9"
|
240
|
-
fail UsageError,
|
241
|
-
"Cannot mock the allocation method using new_instances in Ruby 1.9"
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
255
|
# The singleton class of the object.
|
246
256
|
def target_singleton_class
|
247
|
-
|
257
|
+
@obj.singleton_class
|
248
258
|
end
|
249
259
|
|
250
260
|
# Evaluate a block (or string) in the context of the singleton
|
@@ -253,8 +263,20 @@ class FlexMock
|
|
253
263
|
target_singleton_class.class_eval(*args, &block)
|
254
264
|
end
|
255
265
|
|
256
|
-
|
257
|
-
|
266
|
+
# Evaluate a block into the module we use to define the proxy methods
|
267
|
+
def proxy_module_eval(*args, &block)
|
268
|
+
if !@proxy_definition_module
|
269
|
+
obj = @obj
|
270
|
+
@proxy_definition_module = m = Module.new do
|
271
|
+
define_method(:__flexmock_proxy) do
|
272
|
+
if box = obj.instance_variable_get(:@flexmock_proxy)
|
273
|
+
box.proxy
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
target_class_eval { prepend m }
|
278
|
+
end
|
279
|
+
@proxy_definition_module.class_eval(*args, &block)
|
258
280
|
end
|
259
281
|
|
260
282
|
# Hide the existing method definition with a singleton defintion
|
@@ -271,109 +293,44 @@ class FlexMock
|
|
271
293
|
# Stow the existing method definition so that it can be recovered
|
272
294
|
# later.
|
273
295
|
def stow_existing_definition(method_name)
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
@method_definitions[method_name] = create_aliased_definition(@obj, new_alias)
|
278
|
-
end
|
279
|
-
remove_current_method(method_name) if singleton?(method_name)
|
280
|
-
end
|
281
|
-
|
282
|
-
# Create a method definition that invokes the original behavior
|
283
|
-
# via the alias.
|
284
|
-
def create_aliased_definition(my_object, new_alias)
|
285
|
-
Proc.new { |*args|
|
286
|
-
block = nil
|
287
|
-
if Proc === args.last
|
288
|
-
block = args.last
|
289
|
-
args = args[0...-1]
|
290
|
-
end
|
291
|
-
my_object.send(new_alias, *args, &block)
|
292
|
-
}
|
293
|
-
end
|
294
|
-
private :create_aliased_definition
|
295
|
-
|
296
|
-
# Create an alias for the existing +method_name+. Returns the new
|
297
|
-
# alias name. If the aliasing process fails (because the method
|
298
|
-
# doesn't really exist, then return nil.
|
299
|
-
def create_alias_for_existing_method(method_name)
|
300
|
-
new_alias = new_name(method_name)
|
301
|
-
unless @obj.respond_to?(new_alias)
|
302
|
-
safe_alias_method(new_alias, method_name)
|
303
|
-
end
|
304
|
-
new_alias
|
305
|
-
end
|
306
|
-
|
307
|
-
# Create an alias for the existing method named +method_name+. It
|
308
|
-
# is possible that +method_name+ is implemented via a
|
309
|
-
# meta-programming, so we provide for the case that the
|
310
|
-
# method_name does not exist.
|
311
|
-
def safe_alias_method(new_alias, method_name)
|
312
|
-
target_class_eval do
|
313
|
-
begin
|
314
|
-
alias_method(new_alias, method_name)
|
315
|
-
rescue NameError
|
316
|
-
nil
|
317
|
-
end
|
296
|
+
if !@methods_proxied.include?(method_name)
|
297
|
+
@method_definitions[method_name] = target_class_eval { instance_method(method_name) }
|
298
|
+
@methods_proxied << method_name
|
318
299
|
end
|
300
|
+
rescue NameError
|
319
301
|
end
|
320
302
|
|
321
303
|
# Define a proxy method that forwards to our mock object. The
|
322
304
|
# proxy method is defined as a singleton method on the object
|
323
305
|
# being mocked.
|
324
306
|
def define_proxy_method(method_name)
|
325
|
-
if method_name
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
instance_variable_get('@flexmock_proxy').
|
330
|
-
mock.__send__(:#{method_name}, *args, &block)
|
307
|
+
if method_name =~ /=$/
|
308
|
+
proxy_module_eval do
|
309
|
+
define_method(method_name) do |*args, &block|
|
310
|
+
__flexmock_proxy.mock.__send__(method_name, *args, &block)
|
331
311
|
end
|
332
|
-
|
312
|
+
end
|
333
313
|
else
|
334
|
-
|
335
|
-
target_class_eval %{
|
314
|
+
proxy_module_eval <<-EOD
|
336
315
|
def #{method_name}(*args, &block)
|
337
|
-
|
338
|
-
mock.#{method_name}(*args, &block)
|
316
|
+
__flexmock_proxy.mock.#{method_name}(*args, &block)
|
339
317
|
end
|
340
|
-
|
341
|
-
_ = true # make rcov recognize the above eval is covered
|
318
|
+
EOD
|
342
319
|
end
|
343
320
|
end
|
344
321
|
|
345
322
|
# Restore the original singleton defintion for method_name that
|
346
323
|
# was saved earlier.
|
347
324
|
def restore_original_definition(method_name)
|
348
|
-
|
349
|
-
|
350
|
-
if method_def
|
351
|
-
the_alias = new_name(method_name)
|
352
|
-
target_class_eval do
|
353
|
-
alias_method(method_name, the_alias)
|
354
|
-
end
|
355
|
-
end
|
356
|
-
rescue NameError => _
|
357
|
-
# Alias attempt failed
|
358
|
-
nil
|
325
|
+
proxy_module_eval do
|
326
|
+
remove_method method_name
|
359
327
|
end
|
360
328
|
end
|
361
329
|
|
362
|
-
# Remove the current method if it is a singleton method of the
|
363
|
-
# object being mocked.
|
364
|
-
def remove_current_method(method_name)
|
365
|
-
target_class_eval { remove_method(method_name) }
|
366
|
-
end
|
367
|
-
|
368
330
|
# Have we been detached from the existing object?
|
369
331
|
def detached?
|
370
332
|
@obj.nil?
|
371
333
|
end
|
372
334
|
|
373
|
-
# Generate a name to be used to alias the original behavior.
|
374
|
-
def new_name(old_name)
|
375
|
-
"flexmock_original_behavior_for_#{old_name}"
|
376
|
-
end
|
377
|
-
|
378
335
|
end
|
379
336
|
end
|