rspec-mocks 3.0.0.beta2 → 3.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/Changelog.md +104 -36
- data/README.md +35 -4
- data/lib/rspec/mocks.rb +52 -13
- data/lib/rspec/mocks/any_instance.rb +10 -0
- data/lib/rspec/mocks/any_instance/chain.rb +17 -0
- data/lib/rspec/mocks/any_instance/expect_chain_chain.rb +1 -1
- data/lib/rspec/mocks/any_instance/expectation_chain.rb +9 -6
- data/lib/rspec/mocks/any_instance/message_chains.rb +10 -1
- data/lib/rspec/mocks/any_instance/proxy.rb +112 -0
- data/lib/rspec/mocks/any_instance/recorder.rb +49 -18
- data/lib/rspec/mocks/any_instance/stub_chain.rb +5 -3
- data/lib/rspec/mocks/any_instance/stub_chain_chain.rb +1 -1
- data/lib/rspec/mocks/argument_list_matcher.rb +5 -3
- data/lib/rspec/mocks/argument_matchers.rb +28 -12
- data/lib/rspec/mocks/configuration.rb +29 -0
- data/lib/rspec/mocks/error_generator.rb +2 -5
- data/lib/rspec/mocks/example_methods.rb +122 -13
- data/lib/rspec/mocks/instance_method_stasher.rb +26 -2
- data/lib/rspec/mocks/marshal_extension.rb +41 -0
- data/lib/rspec/mocks/matchers/expectation_customization.rb +20 -0
- data/lib/rspec/mocks/matchers/receive.rb +6 -20
- data/lib/rspec/mocks/matchers/receive_message_chain.rb +7 -5
- data/lib/rspec/mocks/matchers/receive_messages.rb +1 -2
- data/lib/rspec/mocks/message_chain.rb +9 -9
- data/lib/rspec/mocks/message_expectation.rb +6 -5
- data/lib/rspec/mocks/method_double.rb +67 -10
- data/lib/rspec/mocks/method_reference.rb +1 -1
- data/lib/rspec/mocks/mutate_const.rb +10 -14
- data/lib/rspec/mocks/object_reference.rb +7 -4
- data/lib/rspec/mocks/proxy.rb +95 -8
- data/lib/rspec/mocks/space.rb +58 -9
- data/lib/rspec/mocks/syntax.rb +128 -210
- data/lib/rspec/mocks/targets.rb +6 -8
- data/lib/rspec/mocks/test_double.rb +16 -25
- data/lib/rspec/mocks/verifying_double.rb +15 -12
- data/lib/rspec/mocks/verifying_message_expecation.rb +3 -3
- data/lib/rspec/mocks/verifying_proxy.rb +23 -17
- data/lib/rspec/mocks/version.rb +3 -1
- metadata +29 -257
- metadata.gz.sig +0 -0
- data/features/README.md +0 -75
- data/features/Scope.md +0 -17
- data/features/Upgrade.md +0 -22
- data/features/argument_matchers/README.md +0 -27
- data/features/argument_matchers/explicit.feature +0 -59
- data/features/argument_matchers/general_matchers.feature +0 -85
- data/features/argument_matchers/type_matchers.feature +0 -26
- data/features/message_expectations/README.md +0 -75
- data/features/message_expectations/allow_any_instance_of.feature +0 -26
- data/features/message_expectations/any_instance.feature +0 -43
- data/features/message_expectations/block_local_expectations.feature.pending +0 -55
- data/features/message_expectations/call_original.feature +0 -23
- data/features/message_expectations/expect_message_using_expect.feature +0 -107
- data/features/message_expectations/expect_message_using_should_receive.feature +0 -118
- data/features/message_expectations/message_chains_using_expect.feature +0 -49
- data/features/message_expectations/receive_counts.feature +0 -209
- data/features/message_expectations/warn_when_expectation_is_set_on_nil.feature +0 -50
- data/features/method_stubs/README.md +0 -77
- data/features/method_stubs/allow_any_instance_of.feature +0 -136
- data/features/method_stubs/as_null_object.feature +0 -40
- data/features/method_stubs/receive_message_chain.feature +0 -51
- data/features/method_stubs/simple_return_value_with_allow.feature +0 -44
- data/features/method_stubs/simple_return_value_with_stub.feature +0 -64
- data/features/method_stubs/stub_implementation.feature +0 -48
- data/features/method_stubs/to_ary.feature +0 -51
- data/features/mutating_constants/README.md +0 -82
- data/features/mutating_constants/hiding_defined_constant.feature +0 -64
- data/features/mutating_constants/stub_defined_constant.feature +0 -78
- data/features/mutating_constants/stub_undefined_constant.feature +0 -50
- data/features/outside_rspec/standalone.feature +0 -33
- data/features/spies/spy_partial_mock_method.feature +0 -34
- data/features/spies/spy_pure_mock_method.feature +0 -76
- data/features/spies/spy_unstubbed_method.feature +0 -18
- data/features/step_definitions/additional_cli_steps.rb +0 -11
- data/features/support/env.rb +0 -22
- data/features/support/rubinius.rb +0 -6
- data/features/test_frameworks/test_unit.feature +0 -54
- data/features/verifying_doubles/README.md +0 -17
- data/features/verifying_doubles/class_doubles.feature +0 -73
- data/features/verifying_doubles/dynamic_classes.feature +0 -71
- data/features/verifying_doubles/instance_doubles.feature +0 -103
- data/features/verifying_doubles/object_doubles.feature +0 -65
- data/features/verifying_doubles/partial_doubles.feature +0 -34
- data/lib/rspec/mocks/extensions/marshal.rb +0 -17
- data/lib/rspec/mocks/framework.rb +0 -35
- data/lib/rspec/mocks/method_signature_verifier.rb +0 -207
- data/lib/rspec/mocks/ruby_features.rb +0 -24
- data/spec/rspec/mocks/and_call_original_spec.rb +0 -268
- data/spec/rspec/mocks/and_return_spec.rb +0 -23
- data/spec/rspec/mocks/and_yield_spec.rb +0 -126
- data/spec/rspec/mocks/any_instance/message_chains_spec.rb +0 -41
- data/spec/rspec/mocks/any_instance_spec.rb +0 -1045
- data/spec/rspec/mocks/array_including_matcher_spec.rb +0 -41
- data/spec/rspec/mocks/at_least_spec.rb +0 -123
- data/spec/rspec/mocks/at_most_spec.rb +0 -90
- data/spec/rspec/mocks/before_all_spec.rb +0 -132
- data/spec/rspec/mocks/block_return_value_spec.rb +0 -70
- data/spec/rspec/mocks/combining_implementation_instructions_spec.rb +0 -204
- data/spec/rspec/mocks/configuration_spec.rb +0 -242
- data/spec/rspec/mocks/double_spec.rb +0 -874
- data/spec/rspec/mocks/example_methods_spec.rb +0 -13
- data/spec/rspec/mocks/extensions/marshal_spec.rb +0 -54
- data/spec/rspec/mocks/failing_argument_matchers_spec.rb +0 -184
- data/spec/rspec/mocks/hash_excluding_matcher_spec.rb +0 -67
- data/spec/rspec/mocks/hash_including_matcher_spec.rb +0 -94
- data/spec/rspec/mocks/instance_method_stasher_spec.rb +0 -74
- data/spec/rspec/mocks/matchers/have_received_spec.rb +0 -347
- data/spec/rspec/mocks/matchers/receive_message_chain_spec.rb +0 -198
- data/spec/rspec/mocks/matchers/receive_messages_spec.rb +0 -140
- data/spec/rspec/mocks/matchers/receive_spec.rb +0 -418
- data/spec/rspec/mocks/method_signature_verifier_spec.rb +0 -272
- data/spec/rspec/mocks/methods_spec.rb +0 -26
- data/spec/rspec/mocks/mock_expectation_error_spec.rb +0 -22
- data/spec/rspec/mocks/mock_ordering_spec.rb +0 -114
- data/spec/rspec/mocks/multiple_return_value_spec.rb +0 -132
- data/spec/rspec/mocks/mutate_const_spec.rb +0 -542
- data/spec/rspec/mocks/nil_expectation_warning_spec.rb +0 -52
- data/spec/rspec/mocks/null_object_mock_spec.rb +0 -133
- data/spec/rspec/mocks/once_counts_spec.rb +0 -52
- data/spec/rspec/mocks/options_hash_spec.rb +0 -35
- data/spec/rspec/mocks/order_group_spec.rb +0 -27
- data/spec/rspec/mocks/partial_double_spec.rb +0 -308
- data/spec/rspec/mocks/partial_double_using_mocks_directly_spec.rb +0 -95
- data/spec/rspec/mocks/passing_argument_matchers_spec.rb +0 -145
- data/spec/rspec/mocks/precise_counts_spec.rb +0 -68
- data/spec/rspec/mocks/record_messages_spec.rb +0 -26
- data/spec/rspec/mocks/serialization_spec.rb +0 -90
- data/spec/rspec/mocks/space_spec.rb +0 -244
- data/spec/rspec/mocks/stash_spec.rb +0 -46
- data/spec/rspec/mocks/stub_chain_spec.rb +0 -168
- data/spec/rspec/mocks/stub_implementation_spec.rb +0 -81
- data/spec/rspec/mocks/stub_spec.rb +0 -327
- data/spec/rspec/mocks/stubbed_message_expectations_spec.rb +0 -58
- data/spec/rspec/mocks/syntax_agnostic_message_matchers_spec.rb +0 -101
- data/spec/rspec/mocks/syntax_spec.rb +0 -19
- data/spec/rspec/mocks/test_double_spec.rb +0 -49
- data/spec/rspec/mocks/to_ary_spec.rb +0 -54
- data/spec/rspec/mocks/twice_counts_spec.rb +0 -66
- data/spec/rspec/mocks/verifying_double_spec.rb +0 -590
- data/spec/rspec/mocks/verifying_message_expecation_spec.rb +0 -69
- data/spec/rspec/mocks_spec.rb +0 -192
- data/spec/spec_helper.rb +0 -121
@@ -0,0 +1,10 @@
|
|
1
|
+
%w[
|
2
|
+
any_instance/chain
|
3
|
+
any_instance/stub_chain
|
4
|
+
any_instance/stub_chain_chain
|
5
|
+
any_instance/expect_chain_chain
|
6
|
+
any_instance/expectation_chain
|
7
|
+
any_instance/message_chains
|
8
|
+
any_instance/recorder
|
9
|
+
any_instance/proxy
|
10
|
+
].each { |f| RSpec::Support.require_rspec_mocks(f) }
|
@@ -1,13 +1,20 @@
|
|
1
1
|
module RSpec
|
2
2
|
module Mocks
|
3
|
+
# @private
|
3
4
|
module AnyInstance
|
5
|
+
# @private
|
4
6
|
class Chain
|
5
7
|
def initialize(recorder, *args, &block)
|
6
8
|
@recorder = recorder
|
7
9
|
@expectation_args = args
|
8
10
|
@expectation_block = block
|
11
|
+
@argument_list_matcher = ArgumentListMatcher::MATCH_ALL
|
9
12
|
end
|
10
13
|
|
14
|
+
# @private
|
15
|
+
#
|
16
|
+
# Provides convenience methods for recording customizations on message
|
17
|
+
# expectations.
|
11
18
|
module Customizations
|
12
19
|
# @macro [attach] record
|
13
20
|
# @method $1(*args, &block)
|
@@ -57,6 +64,11 @@ module RSpec
|
|
57
64
|
end
|
58
65
|
end
|
59
66
|
|
67
|
+
# @private
|
68
|
+
def matches_args?(*args)
|
69
|
+
@argument_list_matcher.args_match?(*args)
|
70
|
+
end
|
71
|
+
|
60
72
|
# @private
|
61
73
|
def expectation_fulfilled!
|
62
74
|
@expectation_fulfilled = true
|
@@ -67,6 +79,11 @@ module RSpec
|
|
67
79
|
super
|
68
80
|
end
|
69
81
|
|
82
|
+
def with(*args, &block)
|
83
|
+
@argument_list_matcher = ArgumentListMatcher.new(*args)
|
84
|
+
super
|
85
|
+
end
|
86
|
+
|
70
87
|
private
|
71
88
|
|
72
89
|
def negated?
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module RSpec
|
2
2
|
module Mocks
|
3
3
|
module AnyInstance
|
4
|
-
# @
|
4
|
+
# @private
|
5
5
|
class ExpectationChain < Chain
|
6
6
|
def expectation_fulfilled?
|
7
7
|
@expectation_fulfilled || constrained_to_any_of?(:never, :any_number_of_times)
|
@@ -12,20 +12,23 @@ module RSpec
|
|
12
12
|
super
|
13
13
|
end
|
14
14
|
|
15
|
-
|
15
|
+
private
|
16
|
+
|
16
17
|
def verify_invocation_order(rspec_method_name, *args, &block)
|
17
18
|
end
|
18
19
|
end
|
19
20
|
|
20
|
-
# @
|
21
|
+
# @private
|
21
22
|
class PositiveExpectationChain < ExpectationChain
|
22
23
|
|
23
|
-
|
24
|
+
private
|
24
25
|
|
25
26
|
def create_message_expectation_on(instance)
|
26
27
|
proxy = ::RSpec::Mocks.space.proxy_for(instance)
|
27
|
-
|
28
|
-
|
28
|
+
method_name, opts = @expectation_args
|
29
|
+
opts = (opts || {}).merge(:expected_form => IGNORED_BACKTRACE_LINE)
|
30
|
+
|
31
|
+
me = proxy.add_message_expectation(method_name, opts, &@expectation_block)
|
29
32
|
if RSpec::Mocks.configuration.yield_receiver_to_any_instance_implementation_blocks?
|
30
33
|
me.and_yield_receiver_to_implementation
|
31
34
|
end
|
@@ -32,6 +32,15 @@ module RSpec
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
+
# @private
|
36
|
+
def each_unfulfilled_expectation_matching(method_name, *args)
|
37
|
+
@chains_by_method_name[method_name].each do |chain|
|
38
|
+
if !chain.expectation_fulfilled? && chain.matches_args?(*args)
|
39
|
+
yield chain
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
35
44
|
# @private
|
36
45
|
def all_expectations_fulfilled?
|
37
46
|
@chains_by_method_name.all? do |method_name, chains|
|
@@ -61,7 +70,7 @@ module RSpec
|
|
61
70
|
end
|
62
71
|
end
|
63
72
|
|
64
|
-
|
73
|
+
private
|
65
74
|
|
66
75
|
def raise_if_second_instance_to_receive_message(instance)
|
67
76
|
@instance_with_expectation ||= instance if ExpectationChain === instance
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Mocks
|
3
|
+
module AnyInstance
|
4
|
+
# @private
|
5
|
+
# The `AnyInstance::Recorder` is responsible for redefining the klass's
|
6
|
+
# instance method in order to add any stubs/expectations the first time
|
7
|
+
# the method is called. It's not capable of updating a stub on an instance
|
8
|
+
# that's already been previously stubbed (either directly, or via
|
9
|
+
# `any_instance`).
|
10
|
+
#
|
11
|
+
# This proxy sits in front of the recorder and delegates both to it
|
12
|
+
# and to the `RSpec::Mocks::Proxy` for each already mocked or stubbed
|
13
|
+
# instance of the class, in order to propogates changes to the instances.
|
14
|
+
#
|
15
|
+
# Note that unlike `RSpec::Mocks::Proxy`, this proxy class is stateless
|
16
|
+
# and is not persisted in `RSpec::Mocks.space`.
|
17
|
+
#
|
18
|
+
# Proxying for the message expectation fluent interface (typically chained
|
19
|
+
# off of the return value of one of these methods) is provided by the
|
20
|
+
# `FluentInterfaceProxy` class below.
|
21
|
+
class Proxy
|
22
|
+
def initialize(recorder, target_proxies)
|
23
|
+
@recorder = recorder
|
24
|
+
@target_proxies = target_proxies
|
25
|
+
end
|
26
|
+
|
27
|
+
def klass
|
28
|
+
@recorder.klass
|
29
|
+
end
|
30
|
+
|
31
|
+
def stub(method_name_or_method_map, &block)
|
32
|
+
if Hash === method_name_or_method_map
|
33
|
+
method_name_or_method_map.each do |method_name, return_value|
|
34
|
+
stub(method_name).and_return(return_value)
|
35
|
+
end
|
36
|
+
else
|
37
|
+
perform_proxying(__method__, [method_name_or_method_map], block) do |proxy|
|
38
|
+
proxy.add_stub(method_name_or_method_map, &block)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def unstub(method_name)
|
44
|
+
perform_proxying(__method__, [method_name], nil) do |proxy|
|
45
|
+
proxy.remove_stub_if_present(method_name)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def stub_chain(*chain, &block)
|
50
|
+
perform_proxying(__method__, chain, block) do |proxy|
|
51
|
+
Mocks::StubChain.stub_chain_on(proxy.object, *chain, &block)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def expect_chain(*chain, &block)
|
56
|
+
perform_proxying(__method__, chain, block) do |proxy|
|
57
|
+
Mocks::ExpectChain.expect_chain_on(proxy.object, *chain, &block)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def should_receive(method_name, &block)
|
62
|
+
perform_proxying(__method__, [method_name], block) do |proxy|
|
63
|
+
proxy.add_message_expectation(method_name, &block)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def should_not_receive(method_name, &block)
|
68
|
+
perform_proxying(__method__, [method_name], block) do |proxy|
|
69
|
+
proxy.add_message_expectation(method_name, &block).never
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def perform_proxying(method_name, args, block, &target_proxy_block)
|
76
|
+
recorder_value = @recorder.__send__(method_name, *args, &block)
|
77
|
+
proxy_values = @target_proxies.map(&target_proxy_block)
|
78
|
+
FluentInterfaceProxy.new([recorder_value] + proxy_values)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# @private
|
83
|
+
# Delegates messages to each of the given targets in order to
|
84
|
+
# provide the fluent interface that is available off of message
|
85
|
+
# expectations when dealing with `any_instance`.
|
86
|
+
#
|
87
|
+
# `targets` will typically contain 1 of the `AnyInstance::Recorder`
|
88
|
+
# return values and N `MessageExpectation` instances (one per instance
|
89
|
+
# of the `any_instance` klass).
|
90
|
+
class FluentInterfaceProxy
|
91
|
+
def initialize(targets)
|
92
|
+
@targets = targets
|
93
|
+
end
|
94
|
+
|
95
|
+
if RUBY_VERSION.to_f > 1.8
|
96
|
+
def respond_to_missing?(method_name, include_private = false)
|
97
|
+
super || @targets.first.respond_to?(method_name, include_private)
|
98
|
+
end
|
99
|
+
else
|
100
|
+
def respond_to?(method_name, include_private = false)
|
101
|
+
super || @targets.first.respond_to?(method_name, include_private)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def method_missing(*args, &block)
|
106
|
+
return_values = @targets.map { |t| t.__send__(*args, &block) }
|
107
|
+
FluentInterfaceProxy.new(return_values)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -26,15 +26,9 @@ module RSpec
|
|
26
26
|
# instance of this object that invokes the submitted method.
|
27
27
|
#
|
28
28
|
# @see Methods#stub
|
29
|
-
def stub(
|
30
|
-
|
31
|
-
|
32
|
-
stub(method_name).and_return(return_value)
|
33
|
-
end
|
34
|
-
else
|
35
|
-
observe!(method_name_or_method_map)
|
36
|
-
message_chains.add(method_name_or_method_map, StubChain.new(self, method_name_or_method_map, &block))
|
37
|
-
end
|
29
|
+
def stub(method_name, &block)
|
30
|
+
observe!(method_name)
|
31
|
+
message_chains.add(method_name, StubChain.new(self, method_name, &block))
|
38
32
|
end
|
39
33
|
|
40
34
|
# Initializes the recording a stub chain to be played back against any
|
@@ -49,7 +43,7 @@ module RSpec
|
|
49
43
|
end
|
50
44
|
end
|
51
45
|
|
52
|
-
# @
|
46
|
+
# @private
|
53
47
|
def expect_chain(*method_names_and_optional_return_values, &block)
|
54
48
|
@expectation_set = true
|
55
49
|
normalize_chain(*method_names_and_optional_return_values) do |method_name, args|
|
@@ -69,6 +63,9 @@ module RSpec
|
|
69
63
|
message_chains.add(method_name, PositiveExpectationChain.new(self, method_name, &block))
|
70
64
|
end
|
71
65
|
|
66
|
+
# The opposite of `should_receive`
|
67
|
+
#
|
68
|
+
# @see Methods#should_not_receive
|
72
69
|
def should_not_receive(method_name, &block)
|
73
70
|
should_receive(method_name, &block).never
|
74
71
|
end
|
@@ -82,9 +79,6 @@ module RSpec
|
|
82
79
|
raise RSpec::Mocks::MockExpectationError, "The method `#{method_name}` was not stubbed or was already unstubbed"
|
83
80
|
end
|
84
81
|
message_chains.remove_stub_chains_for!(method_name)
|
85
|
-
::RSpec::Mocks.space.proxies_of(@klass).each do |proxy|
|
86
|
-
stubs[method_name].each { |stub| proxy.remove_single_stub(method_name, stub) }
|
87
|
-
end
|
88
82
|
stubs[method_name].clear
|
89
83
|
stop_observing!(method_name) unless message_chains.has_expectation?(method_name)
|
90
84
|
end
|
@@ -97,9 +91,6 @@ module RSpec
|
|
97
91
|
if @expectation_set && !message_chains.all_expectations_fulfilled?
|
98
92
|
raise RSpec::Mocks::MockExpectationError, "Exactly one instance should have received the following message(s) but didn't: #{message_chains.unfulfilled_expectations.sort.join(', ')}"
|
99
93
|
end
|
100
|
-
ensure
|
101
|
-
stop_all_observation!
|
102
|
-
::RSpec::Mocks.space.remove_any_instance_recorder_for(@klass)
|
103
94
|
end
|
104
95
|
|
105
96
|
# @private
|
@@ -120,14 +111,31 @@ module RSpec
|
|
120
111
|
@played_methods[method_name]
|
121
112
|
end
|
122
113
|
|
114
|
+
# @private
|
123
115
|
def build_alias_method_name(method_name)
|
124
116
|
"__#{method_name}_without_any_instance__"
|
125
117
|
end
|
126
118
|
|
119
|
+
# @private
|
127
120
|
def already_observing?(method_name)
|
128
121
|
@observed_methods.include?(method_name) || super_class_observing?(method_name)
|
129
122
|
end
|
130
123
|
|
124
|
+
# @private
|
125
|
+
def notify_received_message(object, message, args, blk)
|
126
|
+
has_expectation = false
|
127
|
+
|
128
|
+
message_chains.each_unfulfilled_expectation_matching(message, *args) do |expectation|
|
129
|
+
has_expectation = true
|
130
|
+
expectation.expectation_fulfilled!
|
131
|
+
end
|
132
|
+
|
133
|
+
if has_expectation
|
134
|
+
restore_method!(message)
|
135
|
+
mark_invoked!(message)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
131
139
|
protected
|
132
140
|
|
133
141
|
def stop_observing!(method_name)
|
@@ -206,8 +214,13 @@ module RSpec
|
|
206
214
|
end
|
207
215
|
|
208
216
|
def observe!(method_name)
|
217
|
+
allow_no_prepended_module_definition_of(method_name)
|
218
|
+
|
209
219
|
if RSpec::Mocks.configuration.verify_partial_doubles?
|
210
|
-
|
220
|
+
unless public_protected_or_private_method_defined?(method_name)
|
221
|
+
raise MockExpectationError,
|
222
|
+
"#{@klass} does not implement ##{method_name}"
|
223
|
+
end
|
211
224
|
end
|
212
225
|
|
213
226
|
stop_observing!(method_name) if already_observing?(method_name)
|
@@ -225,9 +238,27 @@ module RSpec
|
|
225
238
|
@klass.__send__(:define_method, method_name) do |*args, &blk|
|
226
239
|
klass = ::RSpec::Support.method_handle_for(self, method_name).owner
|
227
240
|
invoked_instance = ::RSpec::Mocks.space.any_instance_recorder_for(klass).instance_that_received(method_name)
|
228
|
-
|
241
|
+
inspect = "#<#{self.class}:#{object_id} #{instance_variables.map { |name| "#{name}=#{instance_variable_get name}" }.join(', ')}>"
|
242
|
+
raise RSpec::Mocks::MockExpectationError, "The message '#{method_name}' was received by #{inspect} but has already been received by #{invoked_instance}"
|
229
243
|
end
|
230
244
|
end
|
245
|
+
|
246
|
+
if Support::RubyFeatures.module_prepends_supported?
|
247
|
+
def allow_no_prepended_module_definition_of(method_name)
|
248
|
+
prepended_modules = @klass.ancestors.take_while { |mod| !(Class === mod) }
|
249
|
+
problem_mod = prepended_modules.find { |mod| mod.method_defined?(method_name) }
|
250
|
+
return unless problem_mod
|
251
|
+
|
252
|
+
raise RSpec::Mocks::MockExpectationError,
|
253
|
+
"Using `any_instance` to stub a method (#{method_name}) that has been " +
|
254
|
+
"defined on a prepended module (#{problem_mod}) is not supported."
|
255
|
+
end
|
256
|
+
else
|
257
|
+
def allow_no_prepended_module_definition_of(method_name)
|
258
|
+
# nothing to do; prepends aren't supported on this version of ruby
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
231
262
|
end
|
232
263
|
end
|
233
264
|
end
|
@@ -9,12 +9,14 @@ module RSpec
|
|
9
9
|
true
|
10
10
|
end
|
11
11
|
|
12
|
-
|
12
|
+
private
|
13
13
|
|
14
14
|
def create_message_expectation_on(instance)
|
15
15
|
proxy = ::RSpec::Mocks.space.proxy_for(instance)
|
16
|
-
|
17
|
-
|
16
|
+
method_name, opts = @expectation_args
|
17
|
+
opts = (opts || {}).merge(:expected_form => IGNORED_BACKTRACE_LINE)
|
18
|
+
|
19
|
+
stub = proxy.add_stub(method_name, opts, &@expectation_block)
|
18
20
|
@recorder.stubs[stub.message] << stub
|
19
21
|
|
20
22
|
if RSpec::Mocks.configuration.yield_receiver_to_any_instance_implementation_blocks?
|
@@ -1,3 +1,6 @@
|
|
1
|
+
# We intentionally do not use the `RSpec::Support.require...` methods
|
2
|
+
# here so that this file can be loaded individually, as documented
|
3
|
+
# below.
|
1
4
|
require 'rspec/mocks/argument_matchers'
|
2
5
|
require 'rspec/support/fuzzy_matcher'
|
3
6
|
|
@@ -32,8 +35,7 @@ module RSpec
|
|
32
35
|
attr_reader :expected_args
|
33
36
|
|
34
37
|
# @api public
|
35
|
-
# @param [Array]
|
36
|
-
# @param [Block] block a block with arity matching the expected
|
38
|
+
# @param [Array] expected_args a list of expected literals and/or argument matchers
|
37
39
|
#
|
38
40
|
# Initializes an `ArgumentListMatcher` with a collection of literal
|
39
41
|
# values and/or argument matchers.
|
@@ -51,7 +53,7 @@ module RSpec
|
|
51
53
|
end
|
52
54
|
|
53
55
|
# @api public
|
54
|
-
# @param [Array]
|
56
|
+
# @param [Array] args
|
55
57
|
#
|
56
58
|
# Matches each element in the `expected_args` against the element in the same
|
57
59
|
# position of the arguments passed to `new`.
|
@@ -115,42 +115,50 @@ module RSpec
|
|
115
115
|
|
116
116
|
alias_method :a_kind_of, :kind_of
|
117
117
|
|
118
|
-
# @
|
118
|
+
# @private
|
119
119
|
def self.anythingize_lonely_keys(*args)
|
120
120
|
hash = args.last.class == Hash ? args.delete_at(-1) : {}
|
121
121
|
args.each { | arg | hash[arg] = AnyArgMatcher.new }
|
122
122
|
hash
|
123
123
|
end
|
124
124
|
|
125
|
-
# @
|
125
|
+
# @private
|
126
126
|
class AnyArgsMatcher
|
127
127
|
def description
|
128
128
|
"any args"
|
129
129
|
end
|
130
130
|
end
|
131
131
|
|
132
|
-
# @
|
132
|
+
# @private
|
133
133
|
class AnyArgMatcher
|
134
134
|
def ===(other)
|
135
135
|
true
|
136
136
|
end
|
137
|
+
|
138
|
+
def description
|
139
|
+
"anything"
|
140
|
+
end
|
137
141
|
end
|
138
142
|
|
139
|
-
# @
|
143
|
+
# @private
|
140
144
|
class NoArgsMatcher
|
141
145
|
def description
|
142
146
|
"no args"
|
143
147
|
end
|
144
148
|
end
|
145
149
|
|
146
|
-
# @
|
150
|
+
# @private
|
147
151
|
class BooleanMatcher
|
148
152
|
def ===(value)
|
149
153
|
true == value || false == value
|
150
154
|
end
|
155
|
+
|
156
|
+
def description
|
157
|
+
"boolean"
|
158
|
+
end
|
151
159
|
end
|
152
160
|
|
153
|
-
# @
|
161
|
+
# @private
|
154
162
|
class BaseHashMatcher
|
155
163
|
def initialize(expected)
|
156
164
|
@expected = expected
|
@@ -169,7 +177,7 @@ module RSpec
|
|
169
177
|
end
|
170
178
|
end
|
171
179
|
|
172
|
-
# @
|
180
|
+
# @private
|
173
181
|
class HashIncludingMatcher < BaseHashMatcher
|
174
182
|
def ===(actual)
|
175
183
|
super(:all?, actual)
|
@@ -180,7 +188,7 @@ module RSpec
|
|
180
188
|
end
|
181
189
|
end
|
182
190
|
|
183
|
-
# @
|
191
|
+
# @private
|
184
192
|
class HashExcludingMatcher < BaseHashMatcher
|
185
193
|
def ===(actual)
|
186
194
|
super(:none?, actual)
|
@@ -191,7 +199,7 @@ module RSpec
|
|
191
199
|
end
|
192
200
|
end
|
193
201
|
|
194
|
-
# @
|
202
|
+
# @private
|
195
203
|
class ArrayIncludingMatcher
|
196
204
|
def initialize(expected)
|
197
205
|
@expected = expected
|
@@ -202,11 +210,11 @@ module RSpec
|
|
202
210
|
end
|
203
211
|
|
204
212
|
def description
|
205
|
-
"array_including(#{@expected.join(",")})"
|
213
|
+
"array_including(#{@expected.join(", ")})"
|
206
214
|
end
|
207
215
|
end
|
208
216
|
|
209
|
-
# @
|
217
|
+
# @private
|
210
218
|
class DuckTypeMatcher
|
211
219
|
def initialize(*methods_to_respond_to)
|
212
220
|
@methods_to_respond_to = methods_to_respond_to
|
@@ -215,9 +223,13 @@ module RSpec
|
|
215
223
|
def ===(value)
|
216
224
|
@methods_to_respond_to.all? {|message| value.respond_to?(message)}
|
217
225
|
end
|
226
|
+
|
227
|
+
def description
|
228
|
+
"duck_type(#{@methods_to_respond_to.map(&:inspect).join(', ')})"
|
229
|
+
end
|
218
230
|
end
|
219
231
|
|
220
|
-
# @
|
232
|
+
# @private
|
221
233
|
class InstanceOf
|
222
234
|
def initialize(klass)
|
223
235
|
@klass = klass
|
@@ -226,6 +238,10 @@ module RSpec
|
|
226
238
|
def ===(actual)
|
227
239
|
actual.instance_of?(@klass)
|
228
240
|
end
|
241
|
+
|
242
|
+
def description
|
243
|
+
"an_instance_of(#{@klass.name})"
|
244
|
+
end
|
229
245
|
end
|
230
246
|
|
231
247
|
end
|