rspec-mocks 3.0.0.beta1 → 3.0.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +1 -1
- data/Changelog.md +95 -3
- data/README.md +27 -13
- data/features/README.md +15 -7
- data/features/argument_matchers/README.md +5 -5
- data/features/argument_matchers/explicit.feature +6 -6
- data/features/argument_matchers/general_matchers.feature +4 -4
- data/features/argument_matchers/type_matchers.feature +2 -2
- data/features/message_expectations/README.md +29 -27
- data/features/message_expectations/call_original.feature +0 -1
- data/features/message_expectations/message_chains_using_expect.feature +49 -0
- data/features/method_stubs/README.md +2 -1
- data/features/method_stubs/{any_instance.feature → allow_any_instance_of.feature} +12 -12
- data/features/method_stubs/{stub_chain.feature → receive_message_chain.feature} +3 -3
- data/features/method_stubs/to_ary.feature +1 -1
- data/features/mutating_constants/stub_defined_constant.feature +0 -1
- data/features/outside_rspec/standalone.feature +1 -1
- data/features/spies/spy_pure_mock_method.feature +1 -1
- data/features/test_frameworks/test_unit.feature +21 -10
- data/features/verifying_doubles/README.md +17 -0
- data/features/verifying_doubles/class_doubles.feature +1 -16
- data/features/verifying_doubles/dynamic_classes.feature +0 -1
- data/features/verifying_doubles/{introduction.feature → instance_doubles.feature} +41 -23
- data/features/verifying_doubles/partial_doubles.feature +2 -2
- data/lib/rspec/mocks.rb +69 -82
- data/lib/rspec/mocks/any_instance/expect_chain_chain.rb +35 -0
- data/lib/rspec/mocks/any_instance/expectation_chain.rb +1 -2
- data/lib/rspec/mocks/any_instance/recorder.rb +52 -18
- data/lib/rspec/mocks/any_instance/stub_chain.rb +1 -1
- data/lib/rspec/mocks/any_instance/stub_chain_chain.rb +4 -0
- data/lib/rspec/mocks/argument_list_matcher.rb +10 -44
- data/lib/rspec/mocks/argument_matchers.rb +132 -163
- data/lib/rspec/mocks/configuration.rb +28 -4
- data/lib/rspec/mocks/error_generator.rb +46 -13
- data/lib/rspec/mocks/example_methods.rb +13 -12
- data/lib/rspec/mocks/extensions/marshal.rb +1 -1
- data/lib/rspec/mocks/framework.rb +3 -4
- data/lib/rspec/mocks/instance_method_stasher.rb +2 -3
- data/lib/rspec/mocks/matchers/have_received.rb +8 -6
- data/lib/rspec/mocks/matchers/receive.rb +28 -20
- data/lib/rspec/mocks/matchers/receive_message_chain.rb +65 -0
- data/lib/rspec/mocks/matchers/receive_messages.rb +3 -2
- data/lib/rspec/mocks/message_chain.rb +91 -0
- data/lib/rspec/mocks/message_expectation.rb +86 -80
- data/lib/rspec/mocks/method_double.rb +2 -11
- data/lib/rspec/mocks/method_reference.rb +82 -23
- data/lib/rspec/mocks/method_signature_verifier.rb +207 -0
- data/lib/rspec/mocks/mutate_const.rb +34 -50
- data/lib/rspec/mocks/object_reference.rb +0 -1
- data/lib/rspec/mocks/proxy.rb +70 -13
- data/lib/rspec/mocks/ruby_features.rb +24 -0
- data/lib/rspec/mocks/space.rb +105 -31
- data/lib/rspec/mocks/standalone.rb +2 -2
- data/lib/rspec/mocks/syntax.rb +43 -8
- data/lib/rspec/mocks/targets.rb +16 -7
- data/lib/rspec/mocks/test_double.rb +41 -15
- data/lib/rspec/mocks/verifying_double.rb +51 -4
- data/lib/rspec/mocks/verifying_message_expecation.rb +12 -12
- data/lib/rspec/mocks/verifying_proxy.rb +32 -19
- data/lib/rspec/mocks/version.rb +1 -1
- data/spec/rspec/mocks/and_call_original_spec.rb +28 -7
- data/spec/rspec/mocks/and_return_spec.rb +23 -0
- data/spec/rspec/mocks/and_yield_spec.rb +1 -2
- data/spec/rspec/mocks/any_instance_spec.rb +33 -17
- data/spec/rspec/mocks/array_including_matcher_spec.rb +6 -6
- data/spec/rspec/mocks/before_all_spec.rb +132 -0
- data/spec/rspec/mocks/block_return_value_spec.rb +12 -1
- data/spec/rspec/mocks/combining_implementation_instructions_spec.rb +9 -11
- data/spec/rspec/mocks/configuration_spec.rb +14 -1
- data/spec/rspec/mocks/double_spec.rb +867 -24
- data/spec/rspec/mocks/example_methods_spec.rb +13 -0
- data/spec/rspec/mocks/extensions/marshal_spec.rb +17 -17
- data/spec/rspec/mocks/failing_argument_matchers_spec.rb +29 -1
- data/spec/rspec/mocks/hash_excluding_matcher_spec.rb +12 -12
- data/spec/rspec/mocks/hash_including_matcher_spec.rb +21 -17
- data/spec/rspec/mocks/instance_method_stasher_spec.rb +2 -3
- data/spec/rspec/mocks/matchers/have_received_spec.rb +7 -0
- data/spec/rspec/mocks/matchers/receive_message_chain_spec.rb +198 -0
- data/spec/rspec/mocks/matchers/receive_messages_spec.rb +2 -2
- data/spec/rspec/mocks/matchers/receive_spec.rb +19 -6
- data/spec/rspec/mocks/method_signature_verifier_spec.rb +272 -0
- data/spec/rspec/mocks/methods_spec.rb +0 -1
- data/spec/rspec/mocks/multiple_return_value_spec.rb +2 -2
- data/spec/rspec/mocks/mutate_const_spec.rb +24 -1
- data/spec/rspec/mocks/nil_expectation_warning_spec.rb +6 -22
- data/spec/rspec/mocks/null_object_mock_spec.rb +13 -7
- data/spec/rspec/mocks/options_hash_spec.rb +3 -3
- data/spec/rspec/mocks/{partial_mock_spec.rb → partial_double_spec.rb} +5 -2
- data/spec/rspec/mocks/{partial_mock_using_mocks_directly_spec.rb → partial_double_using_mocks_directly_spec.rb} +1 -1
- data/spec/rspec/mocks/passing_argument_matchers_spec.rb +18 -0
- data/spec/rspec/mocks/serialization_spec.rb +1 -0
- data/spec/rspec/mocks/space_spec.rb +218 -7
- data/spec/rspec/mocks/stub_chain_spec.rb +6 -0
- data/spec/rspec/mocks/stub_spec.rb +0 -6
- data/spec/rspec/mocks/syntax_spec.rb +19 -0
- data/spec/rspec/mocks/test_double_spec.rb +0 -1
- data/spec/rspec/mocks/verifying_double_spec.rb +281 -18
- data/spec/rspec/mocks/verifying_message_expecation_spec.rb +7 -6
- data/spec/rspec/mocks_spec.rb +168 -42
- data/spec/spec_helper.rb +34 -22
- metadata +94 -63
- metadata.gz.sig +0 -0
- checksums.yaml +0 -15
- checksums.yaml.gz.sig +0 -2
- data/features/outside_rspec/configuration.feature +0 -60
- data/lib/rspec/mocks/arity_calculator.rb +0 -66
- data/lib/rspec/mocks/errors.rb +0 -12
- data/lib/rspec/mocks/mock.rb +0 -7
- data/lib/rspec/mocks/proxy_for_nil.rb +0 -37
- data/lib/rspec/mocks/stub_chain.rb +0 -51
- data/spec/rspec/mocks/argument_expectation_spec.rb +0 -32
- data/spec/rspec/mocks/arity_calculator_spec.rb +0 -95
- data/spec/rspec/mocks/mock_space_spec.rb +0 -113
- data/spec/rspec/mocks/mock_spec.rb +0 -788
data/lib/rspec/mocks/targets.rb
CHANGED
@@ -1,8 +1,5 @@
|
|
1
1
|
module RSpec
|
2
2
|
module Mocks
|
3
|
-
UnsupportedMatcherError = Class.new(StandardError)
|
4
|
-
NegationUnsupportedError = Class.new(StandardError)
|
5
|
-
|
6
3
|
class TargetBase
|
7
4
|
def initialize(target)
|
8
5
|
@target = target
|
@@ -10,7 +7,7 @@ module RSpec
|
|
10
7
|
|
11
8
|
def self.delegate_to(matcher_method)
|
12
9
|
define_method(:to) do |matcher, &block|
|
13
|
-
unless
|
10
|
+
unless matcher_allowed?(matcher)
|
14
11
|
raise_unsupported_matcher(:to, matcher)
|
15
12
|
end
|
16
13
|
define_matcher(matcher, matcher_method, &block)
|
@@ -21,8 +18,10 @@ module RSpec
|
|
21
18
|
method_name = options.fetch(:from)
|
22
19
|
define_method(method_name) do |matcher, &block|
|
23
20
|
case matcher
|
24
|
-
when Matchers::Receive
|
25
|
-
|
21
|
+
when Matchers::Receive
|
22
|
+
define_matcher(matcher, matcher_method, &block)
|
23
|
+
when Matchers::ReceiveMessages, Matchers::ReceiveMessageChain
|
24
|
+
raise_negation_unsupported(method_name, matcher)
|
26
25
|
else
|
27
26
|
raise_unsupported_matcher(method_name, matcher)
|
28
27
|
end
|
@@ -37,6 +36,17 @@ module RSpec
|
|
37
36
|
|
38
37
|
private
|
39
38
|
|
39
|
+
def matcher_allowed?(matcher)
|
40
|
+
ALLOWED_MATCHERS.include?(matcher.class)
|
41
|
+
end
|
42
|
+
|
43
|
+
#@api private
|
44
|
+
ALLOWED_MATCHERS = [
|
45
|
+
Matchers::Receive,
|
46
|
+
Matchers::ReceiveMessages,
|
47
|
+
Matchers::ReceiveMessageChain,
|
48
|
+
]
|
49
|
+
|
40
50
|
def define_matcher(matcher, name, &block)
|
41
51
|
matcher.__send__(name, @target, &block)
|
42
52
|
end
|
@@ -87,4 +97,3 @@ module RSpec
|
|
87
97
|
end
|
88
98
|
end
|
89
99
|
end
|
90
|
-
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module RSpec
|
2
2
|
module Mocks
|
3
|
-
# Implements the methods needed for a pure test double. RSpec::Mocks::
|
3
|
+
# Implements the methods needed for a pure test double. RSpec::Mocks::Double
|
4
4
|
# includes this module, and it is provided for cases where you want a
|
5
|
-
# pure test double without subclassing RSpec::Mocks::
|
5
|
+
# pure test double without subclassing RSpec::Mocks::Double.
|
6
6
|
module TestDouble
|
7
7
|
# Extends the TestDouble module onto the given object and
|
8
8
|
# initializes it as a test double.
|
@@ -53,8 +53,6 @@ module RSpec
|
|
53
53
|
inspect.gsub('<','[').gsub('>',']')
|
54
54
|
end
|
55
55
|
|
56
|
-
alias_method :to_str, :to_s
|
57
|
-
|
58
56
|
# @private
|
59
57
|
def respond_to?(message, incl_private=false)
|
60
58
|
__mock_proxy.null_object? ? true : super
|
@@ -62,12 +60,17 @@ module RSpec
|
|
62
60
|
|
63
61
|
# @private
|
64
62
|
def __build_mock_proxy(order_group)
|
65
|
-
|
63
|
+
__raise_expired_error or TestDoubleProxy.new(self, order_group, @name)
|
64
|
+
end
|
65
|
+
|
66
|
+
def __disallow_further_usage!
|
67
|
+
@__expired = true
|
66
68
|
end
|
67
69
|
|
68
70
|
private
|
69
71
|
|
70
72
|
def __initialize_as_test_double(name=nil, stubs={})
|
73
|
+
@__expired = false
|
71
74
|
if Hash === name && stubs.empty?
|
72
75
|
stubs = name
|
73
76
|
@name = nil
|
@@ -78,21 +81,33 @@ module RSpec
|
|
78
81
|
end
|
79
82
|
|
80
83
|
def method_missing(message, *args, &block)
|
81
|
-
|
84
|
+
proxy = __mock_proxy
|
85
|
+
proxy.record_message_received(message, *args, &block)
|
86
|
+
|
87
|
+
if proxy.null_object?
|
82
88
|
case message
|
83
89
|
when :to_int then return 0
|
84
90
|
when :to_a, :to_ary then return nil
|
91
|
+
else return self
|
85
92
|
end
|
86
93
|
end
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
94
|
+
|
95
|
+
# Defined private and protected methods will still trigger `method_missing`
|
96
|
+
# when called publicly. We want ruby's method visibility error to get raised,
|
97
|
+
# so we simply delegate to `super` in that case.
|
98
|
+
# ...well, we would delegate to `super`, but there's a JRuby
|
99
|
+
# bug, so we raise our own visibility error instead:
|
100
|
+
# https://github.com/jruby/jruby/issues/1398
|
101
|
+
visibility = proxy.visibility_for(message)
|
102
|
+
if visibility == :private || visibility == :protected
|
103
|
+
ErrorGenerator.new(self, @name).raise_non_public_error(
|
104
|
+
message, visibility
|
105
|
+
)
|
95
106
|
end
|
107
|
+
|
108
|
+
# Required wrapping doubles in an Array on Ruby 1.9.2
|
109
|
+
raise NoMethodError if [:to_a, :to_ary].include? message
|
110
|
+
proxy.raise_unexpected_message_error(message, *args)
|
96
111
|
end
|
97
112
|
|
98
113
|
def assign_stubs(stubs)
|
@@ -102,8 +117,19 @@ module RSpec
|
|
102
117
|
end
|
103
118
|
|
104
119
|
def __mock_proxy
|
105
|
-
::RSpec::Mocks.proxy_for(self)
|
120
|
+
::RSpec::Mocks.space.proxy_for(self)
|
121
|
+
end
|
122
|
+
|
123
|
+
def __raise_expired_error
|
124
|
+
return false unless @__expired
|
125
|
+
ErrorGenerator.new(self, @name).raise_expired_test_double_error
|
106
126
|
end
|
107
127
|
end
|
128
|
+
|
129
|
+
# A generic test double object. `double`, `instance_double` and friends
|
130
|
+
# return an instance of this.
|
131
|
+
class Double
|
132
|
+
include TestDouble
|
133
|
+
end
|
108
134
|
end
|
109
135
|
end
|
@@ -1,22 +1,63 @@
|
|
1
|
-
require 'rspec/mocks/mock'
|
2
1
|
require 'rspec/mocks/verifying_proxy'
|
2
|
+
require 'stringio'
|
3
3
|
|
4
4
|
module RSpec
|
5
5
|
module Mocks
|
6
6
|
|
7
|
+
# @api private
|
7
8
|
module VerifyingDouble
|
9
|
+
def respond_to?(message, include_private=false)
|
10
|
+
return super unless null_object?
|
11
|
+
|
12
|
+
method_ref = __mock_proxy.method_reference[message]
|
13
|
+
|
14
|
+
return case method_ref.visibility
|
15
|
+
when :public then true
|
16
|
+
when :private then include_private
|
17
|
+
when :protected then include_private || RUBY_VERSION.to_f < 2.0
|
18
|
+
else !method_ref.unimplemented?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
8
22
|
def method_missing(message, *args, &block)
|
9
23
|
# Null object conditional is an optimization. If not a null object,
|
10
24
|
# validity of method expectations will have been checked at definition
|
11
25
|
# time.
|
12
|
-
|
26
|
+
if null_object?
|
27
|
+
if @__sending_message == message
|
28
|
+
__mock_proxy.ensure_implemented(message)
|
29
|
+
else
|
30
|
+
__mock_proxy.ensure_publicly_implemented(message, self)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
super
|
35
|
+
end
|
36
|
+
|
37
|
+
# Redefining `__send__` causes ruby to issue a warning.
|
38
|
+
old, $stderr = $stderr, StringIO.new
|
39
|
+
def __send__(name, *args, &block)
|
40
|
+
@__sending_message = name
|
13
41
|
super
|
42
|
+
ensure
|
43
|
+
@__sending_message = nil
|
44
|
+
end
|
45
|
+
$stderr = old
|
46
|
+
|
47
|
+
def send(name, *args, &block)
|
48
|
+
__send__(name, *args, &block)
|
49
|
+
end
|
50
|
+
|
51
|
+
def __initialize_as_test_double(*args)
|
52
|
+
super
|
53
|
+
@__sending_message = nil
|
14
54
|
end
|
15
55
|
end
|
16
56
|
|
17
57
|
# A mock providing a custom proxy that can verify the validity of any
|
18
58
|
# method stubs or expectations against the public instance methods of the
|
19
59
|
# given class.
|
60
|
+
# @api private
|
20
61
|
class InstanceVerifyingDouble
|
21
62
|
include TestDouble
|
22
63
|
include VerifyingDouble
|
@@ -24,7 +65,10 @@ module RSpec
|
|
24
65
|
def initialize(doubled_module, *args)
|
25
66
|
@doubled_module = doubled_module
|
26
67
|
|
27
|
-
__initialize_as_test_double(
|
68
|
+
__initialize_as_test_double(
|
69
|
+
"#{doubled_module.description} (instance)",
|
70
|
+
*args
|
71
|
+
)
|
28
72
|
end
|
29
73
|
|
30
74
|
def __build_mock_proxy(order_group)
|
@@ -37,6 +81,7 @@ module RSpec
|
|
37
81
|
|
38
82
|
# An awkward module necessary because we cannot otherwise have
|
39
83
|
# ClassVerifyingDouble inherit from Module and still share these methods.
|
84
|
+
# @api private
|
40
85
|
module ObjectVerifyingDoubleMethods
|
41
86
|
include TestDouble
|
42
87
|
include VerifyingDouble
|
@@ -44,7 +89,7 @@ module RSpec
|
|
44
89
|
def initialize(doubled_module, *args)
|
45
90
|
@doubled_module = doubled_module
|
46
91
|
|
47
|
-
__initialize_as_test_double(doubled_module, *args)
|
92
|
+
__initialize_as_test_double(doubled_module.description, *args)
|
48
93
|
end
|
49
94
|
|
50
95
|
def __build_mock_proxy(order_group)
|
@@ -62,6 +107,7 @@ module RSpec
|
|
62
107
|
|
63
108
|
# Similar to an InstanceVerifyingDouble, except that it verifies against
|
64
109
|
# public methods of the given object.
|
110
|
+
# @api private
|
65
111
|
class ObjectVerifyingDouble
|
66
112
|
include ObjectVerifyingDoubleMethods
|
67
113
|
end
|
@@ -69,6 +115,7 @@ module RSpec
|
|
69
115
|
# Effectively the same as an ObjectVerifyingDouble (since a class is a type
|
70
116
|
# of object), except with Module in the inheritance chain so that
|
71
117
|
# transferring nested constants to work.
|
118
|
+
# @api private
|
72
119
|
class ClassVerifyingDouble < Module
|
73
120
|
include ObjectVerifyingDoubleMethods
|
74
121
|
end
|
@@ -1,11 +1,12 @@
|
|
1
|
-
require 'rspec/mocks/
|
1
|
+
require 'rspec/mocks/method_signature_verifier'
|
2
2
|
|
3
3
|
module RSpec
|
4
4
|
module Mocks
|
5
5
|
|
6
6
|
# A message expectation that knows about the real implementation of the
|
7
7
|
# message being expected, so that it can verify that any expectations
|
8
|
-
# have the
|
8
|
+
# have the valid arguments.
|
9
|
+
# @api private
|
9
10
|
class VerifyingMessageExpectation < MessageExpectation
|
10
11
|
|
11
12
|
# A level of indirection is used here rather than just passing in the
|
@@ -25,36 +26,35 @@ module RSpec
|
|
25
26
|
# @override
|
26
27
|
def with(*args, &block)
|
27
28
|
unless ArgumentMatchers::AnyArgsMatcher === args.first
|
28
|
-
|
29
|
-
|
29
|
+
expected_args = if ArgumentMatchers::NoArgsMatcher === args.first
|
30
|
+
[]
|
30
31
|
elsif args.length > 0
|
31
|
-
args
|
32
|
+
args
|
32
33
|
else
|
33
34
|
# No arguments given, this will raise.
|
34
35
|
super
|
35
36
|
end
|
36
37
|
|
37
|
-
|
38
|
+
validate_arguments!(expected_args)
|
38
39
|
end
|
39
40
|
super
|
40
41
|
end
|
41
42
|
|
42
43
|
private
|
43
44
|
|
44
|
-
def
|
45
|
+
def validate_arguments!(actual_args)
|
45
46
|
return if method_reference.nil?
|
46
47
|
|
47
|
-
method_reference.
|
48
|
-
|
49
|
-
unless
|
48
|
+
method_reference.with_signature do |signature|
|
49
|
+
verifier = MethodSignatureVerifier.new(signature, actual_args)
|
50
|
+
unless verifier.valid?
|
50
51
|
# Fail fast is required, otherwise the message expecation will fail
|
51
52
|
# as well ("expected method not called") and clobber this one.
|
52
53
|
@failed_fast = true
|
53
|
-
@error_generator.
|
54
|
+
@error_generator.raise_invalid_arguments_error(verifier)
|
54
55
|
end
|
55
56
|
end
|
56
57
|
end
|
57
58
|
end
|
58
59
|
end
|
59
60
|
end
|
60
|
-
|
@@ -4,6 +4,7 @@ require 'rspec/mocks/method_reference'
|
|
4
4
|
module RSpec
|
5
5
|
module Mocks
|
6
6
|
|
7
|
+
# @api private
|
7
8
|
module VerifyingProxyMethods
|
8
9
|
def add_stub(location, method_name, opts={}, &implementation)
|
9
10
|
ensure_implemented(method_name)
|
@@ -21,21 +22,28 @@ module RSpec
|
|
21
22
|
end
|
22
23
|
|
23
24
|
def ensure_implemented(method_name)
|
24
|
-
|
25
|
-
|
26
|
-
method_reference[method_name].when_unimplemented do
|
25
|
+
if method_reference[method_name].unimplemented?
|
27
26
|
@error_generator.raise_unimplemented_error(
|
28
27
|
@doubled_module,
|
29
28
|
method_name
|
30
29
|
)
|
31
30
|
end
|
32
31
|
end
|
32
|
+
|
33
|
+
def ensure_publicly_implemented(method_name, object)
|
34
|
+
ensure_implemented(method_name)
|
35
|
+
visibility = method_reference[method_name].visibility
|
36
|
+
|
37
|
+
unless visibility == :public
|
38
|
+
@error_generator.raise_non_public_error(method_name, visibility)
|
39
|
+
end
|
40
|
+
end
|
33
41
|
end
|
34
42
|
|
35
43
|
# A verifying proxy mostly acts like a normal proxy, except that it
|
36
44
|
# contains extra logic to try and determine the validity of any expectation
|
37
45
|
# set on it. This includes whether or not methods have been defined and the
|
38
|
-
#
|
46
|
+
# validatiy of arguments on method calls.
|
39
47
|
#
|
40
48
|
# In all other ways this behaves like a normal proxy. It only adds the
|
41
49
|
# verification behaviour to specific methods then delegates to the parent
|
@@ -56,7 +64,7 @@ module RSpec
|
|
56
64
|
@method_reference_class = method_reference_class
|
57
65
|
|
58
66
|
# A custom method double is required to pass through a way to lookup
|
59
|
-
# methods to determine their
|
67
|
+
# methods to determine their parameters. This is only relevant if the doubled
|
60
68
|
# class is loaded.
|
61
69
|
@method_doubles = Hash.new do |h, k|
|
62
70
|
h[k] = VerifyingMethodDouble.new(@object, k, self, method_reference[k])
|
@@ -68,9 +76,14 @@ module RSpec
|
|
68
76
|
h[k] = @method_reference_class.new(@doubled_module, k)
|
69
77
|
end
|
70
78
|
end
|
79
|
+
|
80
|
+
def visibility_for(method_name)
|
81
|
+
method_reference[method_name].visibility
|
82
|
+
end
|
71
83
|
end
|
72
84
|
|
73
|
-
|
85
|
+
# @api private
|
86
|
+
class VerifyingPartialDoubleProxy < PartialDoubleProxy
|
74
87
|
include VerifyingProxyMethods
|
75
88
|
|
76
89
|
def initialize(object, expectation_ordering)
|
@@ -78,7 +91,7 @@ module RSpec
|
|
78
91
|
@doubled_module = DirectObjectReference.new(object)
|
79
92
|
|
80
93
|
# A custom method double is required to pass through a way to lookup
|
81
|
-
# methods to determine their
|
94
|
+
# methods to determine their parameters.
|
82
95
|
@method_doubles = Hash.new do |h, k|
|
83
96
|
h[k] = VerifyingExistingMethodDouble.new(object, k, self)
|
84
97
|
end
|
@@ -105,29 +118,29 @@ module RSpec
|
|
105
118
|
end
|
106
119
|
|
107
120
|
def proxy_method_invoked(obj, *args, &block)
|
108
|
-
|
121
|
+
validate_arguments!(args)
|
109
122
|
super
|
110
123
|
end
|
111
124
|
|
112
125
|
private
|
113
126
|
|
114
|
-
def
|
115
|
-
@method_reference.
|
116
|
-
|
117
|
-
unless
|
118
|
-
raise ArgumentError,
|
127
|
+
def validate_arguments!(actual_args)
|
128
|
+
@method_reference.with_signature do |signature|
|
129
|
+
verifier = MethodSignatureVerifier.new(signature, actual_args)
|
130
|
+
unless verifier.valid?
|
131
|
+
raise ArgumentError, verifier.error_message
|
119
132
|
end
|
120
133
|
end
|
121
134
|
end
|
122
135
|
end
|
123
136
|
|
124
|
-
# @api private
|
125
|
-
#
|
126
137
|
# A VerifyingMethodDouble fetches the method to verify against from the
|
127
138
|
# original object, using a MethodReference. This works for pure doubles,
|
128
139
|
# but when the original object is itself the one being modified we need to
|
129
140
|
# collapse the reference and the method double into a single object so that
|
130
141
|
# we can access the original pristine method definition.
|
142
|
+
#
|
143
|
+
# @api private
|
131
144
|
class VerifyingExistingMethodDouble < VerifyingMethodDouble
|
132
145
|
def initialize(object, method_name, proxy)
|
133
146
|
super(object, method_name, proxy, self)
|
@@ -139,12 +152,12 @@ module RSpec
|
|
139
152
|
save_original_method!
|
140
153
|
end
|
141
154
|
|
142
|
-
def
|
143
|
-
yield original_method
|
155
|
+
def with_signature
|
156
|
+
yield MethodSignature.new(original_method)
|
144
157
|
end
|
145
158
|
|
146
|
-
def
|
147
|
-
|
159
|
+
def unimplemented?
|
160
|
+
!@valid_method
|
148
161
|
end
|
149
162
|
end
|
150
163
|
end
|