rspec-mocks 3.0.0.beta1 → 3.0.0.beta2
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.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
|