rspec-mocks 2.99.4 → 3.0.0.beta1
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.
- checksums.yaml +14 -6
- checksums.yaml.gz.sig +2 -0
- data.tar.gz.sig +1 -0
- data/Changelog.md +89 -105
- data/License.txt +1 -0
- data/README.md +77 -57
- data/features/argument_matchers/explicit.feature +5 -5
- data/features/argument_matchers/general_matchers.feature +10 -10
- data/features/argument_matchers/type_matchers.feature +3 -3
- data/features/message_expectations/allow_any_instance_of.feature +1 -1
- data/features/message_expectations/any_instance.feature +27 -5
- data/features/message_expectations/call_original.feature +2 -2
- data/features/message_expectations/expect_message_using_expect.feature +2 -2
- data/features/message_expectations/expect_message_using_should_receive.feature +2 -2
- data/features/message_expectations/receive_counts.feature +7 -7
- data/features/message_expectations/warn_when_expectation_is_set_on_nil.feature +3 -3
- data/features/method_stubs/README.md +3 -0
- data/features/method_stubs/any_instance.feature +11 -11
- data/features/method_stubs/as_null_object.feature +4 -4
- data/features/method_stubs/simple_return_value_with_stub.feature +7 -7
- data/features/method_stubs/stub_chain.feature +3 -3
- data/features/method_stubs/stub_implementation.feature +2 -2
- data/features/method_stubs/to_ary.feature +2 -2
- data/features/mutating_constants/hiding_defined_constant.feature +2 -2
- data/features/mutating_constants/stub_defined_constant.feature +5 -5
- data/features/mutating_constants/stub_undefined_constant.feature +6 -6
- data/features/outside_rspec/configuration.feature +0 -2
- data/features/outside_rspec/standalone.feature +1 -1
- data/features/spies/spy_partial_mock_method.feature +2 -2
- data/features/spies/spy_pure_mock_method.feature +5 -5
- data/features/spies/spy_unstubbed_method.feature +1 -1
- data/features/support/env.rb +10 -1
- data/features/test_frameworks/test_unit.feature +1 -1
- data/features/verifying_doubles/class_doubles.feature +88 -0
- data/features/verifying_doubles/dynamic_classes.feature +72 -0
- data/features/verifying_doubles/introduction.feature +85 -0
- data/features/verifying_doubles/object_doubles.feature +65 -0
- data/features/verifying_doubles/partial_doubles.feature +34 -0
- data/lib/rspec/mocks.rb +8 -34
- data/lib/rspec/mocks/any_instance/chain.rb +4 -34
- data/lib/rspec/mocks/any_instance/expectation_chain.rb +14 -4
- data/lib/rspec/mocks/any_instance/message_chains.rb +27 -12
- data/lib/rspec/mocks/any_instance/recorder.rb +23 -31
- data/lib/rspec/mocks/any_instance/stub_chain.rb +9 -4
- data/lib/rspec/mocks/argument_list_matcher.rb +8 -1
- data/lib/rspec/mocks/argument_matchers.rb +26 -12
- data/lib/rspec/mocks/arity_calculator.rb +66 -0
- data/lib/rspec/mocks/configuration.rb +42 -14
- data/lib/rspec/mocks/error_generator.rb +34 -10
- data/lib/rspec/mocks/example_methods.rb +64 -19
- data/lib/rspec/mocks/extensions/marshal.rb +0 -15
- data/lib/rspec/mocks/framework.rb +4 -4
- data/lib/rspec/mocks/instance_method_stasher.rb +80 -62
- data/lib/rspec/mocks/matchers/have_received.rb +18 -14
- data/lib/rspec/mocks/matchers/receive.rb +29 -7
- data/lib/rspec/mocks/matchers/receive_messages.rb +72 -0
- data/lib/rspec/mocks/message_expectation.rb +95 -148
- data/lib/rspec/mocks/method_double.rb +77 -139
- data/lib/rspec/mocks/method_reference.rb +95 -0
- data/lib/rspec/mocks/mock.rb +1 -1
- data/lib/rspec/mocks/mutate_const.rb +12 -9
- data/lib/rspec/mocks/object_reference.rb +90 -0
- data/lib/rspec/mocks/order_group.rb +49 -7
- data/lib/rspec/mocks/proxy.rb +72 -33
- data/lib/rspec/mocks/proxy_for_nil.rb +2 -2
- data/lib/rspec/mocks/space.rb +13 -18
- data/lib/rspec/mocks/stub_chain.rb +2 -2
- data/lib/rspec/mocks/syntax.rb +61 -36
- data/lib/rspec/mocks/targets.rb +40 -19
- data/lib/rspec/mocks/test_double.rb +12 -56
- data/lib/rspec/mocks/verifying_double.rb +77 -0
- data/lib/rspec/mocks/verifying_message_expecation.rb +60 -0
- data/lib/rspec/mocks/verifying_proxy.rb +151 -0
- data/lib/rspec/mocks/version.rb +1 -1
- data/spec/rspec/mocks/and_call_original_spec.rb +34 -30
- data/spec/rspec/mocks/and_yield_spec.rb +2 -2
- data/spec/rspec/mocks/any_instance/message_chains_spec.rb +1 -1
- data/spec/rspec/mocks/any_instance_spec.rb +53 -260
- data/spec/rspec/mocks/argument_expectation_spec.rb +4 -4
- data/spec/rspec/mocks/arity_calculator_spec.rb +95 -0
- data/spec/rspec/mocks/array_including_matcher_spec.rb +41 -0
- data/spec/rspec/mocks/at_least_spec.rb +4 -32
- data/spec/rspec/mocks/block_return_value_spec.rb +4 -135
- data/spec/rspec/mocks/combining_implementation_instructions_spec.rb +10 -11
- data/spec/rspec/mocks/configuration_spec.rb +79 -0
- data/spec/rspec/mocks/double_spec.rb +10 -78
- data/spec/rspec/mocks/extensions/marshal_spec.rb +0 -8
- data/spec/rspec/mocks/failing_argument_matchers_spec.rb +49 -4
- data/spec/rspec/mocks/instance_method_stasher_spec.rb +20 -3
- data/spec/rspec/mocks/matchers/have_received_spec.rb +74 -0
- data/spec/rspec/mocks/matchers/receive_messages_spec.rb +140 -0
- data/spec/rspec/mocks/matchers/receive_spec.rb +82 -42
- data/spec/rspec/mocks/methods_spec.rb +1 -1
- data/spec/rspec/mocks/{bug_report_830_spec.rb → mock_expectation_error_spec.rb} +4 -3
- data/spec/rspec/mocks/mock_ordering_spec.rb +11 -0
- data/spec/rspec/mocks/mock_space_spec.rb +10 -1
- data/spec/rspec/mocks/mock_spec.rb +26 -82
- data/spec/rspec/mocks/multiple_return_value_spec.rb +1 -1
- data/spec/rspec/mocks/mutate_const_spec.rb +18 -5
- data/spec/rspec/mocks/null_object_mock_spec.rb +6 -4
- data/spec/rspec/mocks/options_hash_spec.rb +3 -3
- data/spec/rspec/mocks/order_group_spec.rb +27 -0
- data/spec/rspec/mocks/partial_mock_spec.rb +101 -1
- data/spec/rspec/mocks/passing_argument_matchers_spec.rb +3 -20
- data/spec/rspec/mocks/record_messages_spec.rb +4 -4
- data/spec/rspec/mocks/serialization_spec.rb +4 -6
- data/spec/rspec/mocks/space_spec.rb +3 -3
- data/spec/rspec/mocks/stub_chain_spec.rb +0 -12
- data/spec/rspec/mocks/stub_spec.rb +23 -44
- data/spec/rspec/mocks/test_double_spec.rb +3 -22
- data/spec/rspec/mocks/verifying_double_spec.rb +327 -0
- data/spec/rspec/mocks/verifying_message_expecation_spec.rb +68 -0
- data/spec/rspec/mocks_spec.rb +16 -39
- data/spec/spec_helper.rb +29 -18
- metadata +131 -86
- metadata.gz.sig +1 -0
- data/features/message_expectations/expect_any_instance_of.feature +0 -27
- data/lib/rspec/mocks/caller_filter.rb +0 -60
- data/lib/rspec/mocks/deprecation.rb +0 -26
- data/lib/rspec/mocks/extensions/instance_exec.rb +0 -34
- data/lib/rspec/mocks/extensions/proc.rb +0 -63
- data/lib/spec/mocks.rb +0 -4
- data/spec/rspec/mocks/and_return_spec.rb +0 -17
- data/spec/rspec/mocks/any_number_of_times_spec.rb +0 -36
- data/spec/rspec/mocks/before_all_spec.rb +0 -74
- data/spec/rspec/mocks/bug_report_10260_spec.rb +0 -8
- data/spec/rspec/mocks/bug_report_10263_spec.rb +0 -27
- data/spec/rspec/mocks/bug_report_11545_spec.rb +0 -32
- data/spec/rspec/mocks/bug_report_496_spec.rb +0 -17
- data/spec/rspec/mocks/bug_report_600_spec.rb +0 -22
- data/spec/rspec/mocks/bug_report_7611_spec.rb +0 -16
- data/spec/rspec/mocks/bug_report_8165_spec.rb +0 -31
- data/spec/rspec/mocks/bug_report_957_spec.rb +0 -22
@@ -0,0 +1,65 @@
|
|
1
|
+
Feature: Using an object double
|
2
|
+
|
3
|
+
`object_double` can be used to create a double from an existing "template"
|
4
|
+
object, from which it verifies that any stubbed methods on the double also
|
5
|
+
exist on the template. This is useful for objects that are readily
|
6
|
+
constructable, but may have far-reaching side-effects such as talking to a
|
7
|
+
database or external API. In this case, using a double rather than the real
|
8
|
+
thing allows you to focus on the communication patterns of the object's
|
9
|
+
interface without having to worry about accidentally causing side-effects.
|
10
|
+
Object doubles can also be used to verify methods defined on an object using
|
11
|
+
`method_missing`, which is not possible with `instance_double`.
|
12
|
+
|
13
|
+
In addition, `object_double` can be used with specific constant values, as
|
14
|
+
shown below. This is for niche situations, such as when dealing with
|
15
|
+
singleton objects.
|
16
|
+
|
17
|
+
Scenario: doubling an existing object
|
18
|
+
Given a file named "spec/user_spec.rb" with:
|
19
|
+
"""ruby
|
20
|
+
class User
|
21
|
+
# Don't want to accidentally trigger this!
|
22
|
+
def save; sleep 100; end
|
23
|
+
end
|
24
|
+
|
25
|
+
def save_user(user)
|
26
|
+
"saved!" if user.save
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#save_user' do
|
30
|
+
it 'renders message on success' do
|
31
|
+
user = object_double(User.new, :save => true)
|
32
|
+
expect(save_user(user)).to eq("saved!")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
"""
|
36
|
+
When I run `rspec spec/user_spec.rb`
|
37
|
+
Then the examples should all pass
|
38
|
+
|
39
|
+
|
40
|
+
Scenario: doubling a constant object
|
41
|
+
Given a file named "spec/email_spec.rb" with:
|
42
|
+
"""ruby
|
43
|
+
require 'logger'
|
44
|
+
|
45
|
+
module MyApp
|
46
|
+
LOGGER = Logger.new("myapp")
|
47
|
+
end
|
48
|
+
|
49
|
+
class Email
|
50
|
+
def self.send_to(recipient)
|
51
|
+
MyApp::LOGGER.info("Sent to #{recipient}")
|
52
|
+
# other emailing logic
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe Email do
|
57
|
+
it 'logs a message when sending' do
|
58
|
+
logger = object_double("MyApp::LOGGER", :info => nil).as_stubbed_const
|
59
|
+
Email.send_to('hello@foo.com')
|
60
|
+
expect(logger).to have_received(:info).with("Sent to hello@foo.com")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
"""
|
64
|
+
When I run `rspec spec/email_spec.rb`
|
65
|
+
Then the examples should all pass
|
@@ -0,0 +1,34 @@
|
|
1
|
+
Feature: Partial doubles
|
2
|
+
|
3
|
+
When the `verify_partial_doubles` configuration option is set, the same arity
|
4
|
+
and method existince checks that are performed for `object_double` are also
|
5
|
+
performed on partial doubles. You should set this unless you have a good
|
6
|
+
reason not to. It defaults to off only for backwards compatibility.
|
7
|
+
|
8
|
+
Scenario: doubling an existing object
|
9
|
+
Given a file named "spec/user_spec.rb" with:
|
10
|
+
"""ruby
|
11
|
+
class User
|
12
|
+
def save; false; end
|
13
|
+
end
|
14
|
+
|
15
|
+
def save_user(user)
|
16
|
+
"saved!" if user.save
|
17
|
+
end
|
18
|
+
|
19
|
+
RSpec.configure do |config|
|
20
|
+
config.mock_with :rspec do |mocks|
|
21
|
+
mocks.verify_partial_doubles = true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#save_user' do
|
26
|
+
it 'renders message on success' do
|
27
|
+
user = User.new
|
28
|
+
expect(user).to receive(:saave).and_return(true) # Typo in name
|
29
|
+
expect(save_user(user)).to eq("saved!")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
"""
|
33
|
+
When I run `rspec spec/user_spec.rb`
|
34
|
+
Then the output should contain "1 example, 1 failure"
|
data/lib/rspec/mocks.rb
CHANGED
@@ -2,25 +2,16 @@ require 'rspec/mocks/framework'
|
|
2
2
|
require 'rspec/mocks/version'
|
3
3
|
|
4
4
|
module RSpec
|
5
|
+
|
5
6
|
module Mocks
|
6
7
|
class << self
|
7
8
|
attr_accessor :space
|
8
9
|
|
9
|
-
def setup(host
|
10
|
-
|
11
|
-
|
12
|
-
unless host_is_from_rspec_core
|
13
|
-
RSpec.deprecate(
|
14
|
-
"The host argument to `RSpec::Mocks.setup`",
|
15
|
-
:replacement => "`include RSpec::Mocks::ExampleMethods` in #{host.inspect}"
|
16
|
-
)
|
17
|
-
end
|
18
|
-
|
19
|
-
(class << host; self; end).class_eval do
|
20
|
-
include RSpec::Mocks::ExampleMethods
|
21
|
-
end
|
10
|
+
def setup(host)
|
11
|
+
(class << host; self; end).class_exec do
|
12
|
+
include RSpec::Mocks::ExampleMethods
|
22
13
|
end
|
23
|
-
space
|
14
|
+
self.space ||= RSpec::Mocks::Space.new
|
24
15
|
end
|
25
16
|
|
26
17
|
def verify
|
@@ -29,7 +20,6 @@ module RSpec
|
|
29
20
|
|
30
21
|
def teardown
|
31
22
|
space.reset_all
|
32
|
-
space.outside_example = true
|
33
23
|
end
|
34
24
|
|
35
25
|
def proxy_for(object)
|
@@ -61,7 +51,7 @@ module RSpec
|
|
61
51
|
CallerFilter.first_non_rspec_line
|
62
52
|
}
|
63
53
|
::RSpec::Mocks.proxy_for(subject).
|
64
|
-
add_stub(orig_caller, message
|
54
|
+
add_stub(orig_caller, message, opts, &block)
|
65
55
|
end
|
66
56
|
|
67
57
|
# Sets a message expectation on `subject`.
|
@@ -80,7 +70,7 @@ module RSpec
|
|
80
70
|
CallerFilter.first_non_rspec_line
|
81
71
|
}
|
82
72
|
::RSpec::Mocks.proxy_for(subject).
|
83
|
-
add_message_expectation(orig_caller, message
|
73
|
+
add_message_expectation(orig_caller, message, opts, &block)
|
84
74
|
end
|
85
75
|
|
86
76
|
# @api private
|
@@ -105,22 +95,6 @@ module RSpec
|
|
105
95
|
|
106
96
|
# @private
|
107
97
|
IGNORED_BACKTRACE_LINE = 'this backtrace line is ignored'
|
108
|
-
|
109
|
-
self.space = RSpec::Mocks::Space.new
|
110
|
-
|
111
|
-
DEPRECATED_CONSTANTS =
|
112
|
-
{
|
113
|
-
:Mock => Double,
|
114
|
-
:ConstantStubber => ConstantMutator,
|
115
|
-
}
|
116
|
-
|
117
|
-
def self.const_missing(name)
|
118
|
-
if const = DEPRECATED_CONSTANTS[name]
|
119
|
-
RSpec.deprecate("RSpec::Mocks::#{name}", :replacement => const.name)
|
120
|
-
const
|
121
|
-
else
|
122
|
-
super
|
123
|
-
end
|
124
|
-
end
|
125
98
|
end
|
126
99
|
end
|
100
|
+
|
@@ -6,8 +6,6 @@ module RSpec
|
|
6
6
|
@recorder = recorder
|
7
7
|
@expectation_args = args
|
8
8
|
@expectation_block = block
|
9
|
-
@source_line = CallerFilter.first_non_rspec_line
|
10
|
-
ensure_expectation_block_has_source_location
|
11
9
|
end
|
12
10
|
|
13
11
|
module Customizations
|
@@ -19,11 +17,9 @@ module RSpec
|
|
19
17
|
# @see RSpec::Mocks::MessageExpectation#$1
|
20
18
|
#
|
21
19
|
def self.record(method_name)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
26
|
-
EOM
|
20
|
+
define_method(method_name) do |*args, &block|
|
21
|
+
record(method_name, *args, &block)
|
22
|
+
end
|
27
23
|
end
|
28
24
|
|
29
25
|
record :and_return
|
@@ -73,21 +69,8 @@ module RSpec
|
|
73
69
|
|
74
70
|
private
|
75
71
|
|
76
|
-
def create_message_expectation_on(instance)
|
77
|
-
me = yield(::RSpec::Mocks.proxy_for(instance), IGNORED_BACKTRACE_LINE)
|
78
|
-
|
79
|
-
if RSpec::Mocks.configuration.should_warn_about_any_instance_blocks?
|
80
|
-
me.warn_about_receiver_passing(@source_line)
|
81
|
-
me.display_any_instance_deprecation_warning_if_necessary(@expectation_block)
|
82
|
-
elsif RSpec::Mocks.configuration.yield_receiver_to_any_instance_implementation_blocks?
|
83
|
-
me.and_yield_receiver_to_implementation
|
84
|
-
end
|
85
|
-
|
86
|
-
me
|
87
|
-
end
|
88
|
-
|
89
72
|
def negated?
|
90
|
-
messages.any? { |(message, *_), _| message
|
73
|
+
messages.any? { |(message, *_), _| message == :never }
|
91
74
|
end
|
92
75
|
|
93
76
|
def messages
|
@@ -103,19 +86,6 @@ module RSpec
|
|
103
86
|
messages << [args.unshift(rspec_method_name), block]
|
104
87
|
self
|
105
88
|
end
|
106
|
-
|
107
|
-
if Proc.method_defined?(:source_location)
|
108
|
-
def ensure_expectation_block_has_source_location; end
|
109
|
-
else
|
110
|
-
def ensure_expectation_block_has_source_location
|
111
|
-
return unless @expectation_block
|
112
|
-
source_location = CallerFilter.first_non_rspec_line.split(':')
|
113
|
-
|
114
|
-
@expectation_block.extend Module.new {
|
115
|
-
define_method(:source_location) { source_location }
|
116
|
-
}
|
117
|
-
end
|
118
|
-
end
|
119
89
|
end
|
120
90
|
end
|
121
91
|
end
|
@@ -12,15 +12,25 @@ module RSpec
|
|
12
12
|
super
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
|
15
|
+
private
|
17
16
|
def verify_invocation_order(rspec_method_name, *args, &block)
|
18
17
|
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# @api private
|
21
|
+
class PositiveExpectationChain < ExpectationChain
|
22
|
+
|
23
|
+
private
|
19
24
|
|
20
25
|
def create_message_expectation_on(instance)
|
21
|
-
|
22
|
-
|
26
|
+
proxy = ::RSpec::Mocks.proxy_for(instance)
|
27
|
+
expected_from = IGNORED_BACKTRACE_LINE
|
28
|
+
me = proxy.add_message_expectation(expected_from, *@expectation_args, &@expectation_block)
|
29
|
+
if RSpec::Mocks.configuration.yield_receiver_to_any_instance_implementation_blocks?
|
30
|
+
me.and_yield_receiver_to_implementation
|
23
31
|
end
|
32
|
+
|
33
|
+
me
|
24
34
|
end
|
25
35
|
|
26
36
|
def invocation_order
|
@@ -2,55 +2,70 @@ module RSpec
|
|
2
2
|
module Mocks
|
3
3
|
module AnyInstance
|
4
4
|
# @private
|
5
|
-
class MessageChains
|
5
|
+
class MessageChains
|
6
6
|
def initialize
|
7
|
-
|
7
|
+
@chains_by_method_name = Hash.new { |h, k| h[k] = [] }
|
8
|
+
end
|
9
|
+
|
10
|
+
# @private
|
11
|
+
def [](method_name)
|
12
|
+
@chains_by_method_name[method_name]
|
8
13
|
end
|
9
14
|
|
10
15
|
# @private
|
11
16
|
def add(method_name, chain)
|
12
|
-
|
17
|
+
@chains_by_method_name[method_name] << chain
|
13
18
|
chain
|
14
19
|
end
|
15
20
|
|
16
21
|
# @private
|
17
22
|
def remove_stub_chains_for!(method_name)
|
18
|
-
|
23
|
+
@chains_by_method_name[method_name].reject! do |chain|
|
24
|
+
StubChain === chain
|
25
|
+
end
|
19
26
|
end
|
20
27
|
|
21
28
|
# @private
|
22
29
|
def has_expectation?(method_name)
|
23
|
-
|
30
|
+
@chains_by_method_name[method_name].find do |chain|
|
31
|
+
ExpectationChain === chain
|
32
|
+
end
|
24
33
|
end
|
25
34
|
|
26
35
|
# @private
|
27
36
|
def all_expectations_fulfilled?
|
28
|
-
all?
|
37
|
+
@chains_by_method_name.all? do |method_name, chains|
|
38
|
+
chains.all? { |chain| chain.expectation_fulfilled? }
|
39
|
+
end
|
29
40
|
end
|
30
41
|
|
31
42
|
# @private
|
32
43
|
def unfulfilled_expectations
|
33
|
-
map do |method_name, chains|
|
34
|
-
method_name.to_s if chains.last
|
44
|
+
@chains_by_method_name.map do |method_name, chains|
|
45
|
+
method_name.to_s if ExpectationChain === chains.last unless chains.last.expectation_fulfilled?
|
35
46
|
end.compact
|
36
47
|
end
|
37
48
|
|
38
49
|
# @private
|
39
50
|
def received_expected_message!(method_name)
|
40
|
-
|
51
|
+
@chains_by_method_name[method_name].each do |chain|
|
52
|
+
chain.expectation_fulfilled!
|
53
|
+
end
|
41
54
|
end
|
42
55
|
|
43
56
|
# @private
|
44
57
|
def playback!(instance, method_name)
|
45
58
|
raise_if_second_instance_to_receive_message(instance)
|
46
|
-
|
59
|
+
@chains_by_method_name[method_name].each do |chain|
|
60
|
+
chain.playback!(instance)
|
61
|
+
end
|
47
62
|
end
|
48
63
|
|
49
64
|
private
|
50
65
|
|
51
66
|
def raise_if_second_instance_to_receive_message(instance)
|
52
|
-
@instance_with_expectation ||= instance if instance
|
53
|
-
if
|
67
|
+
@instance_with_expectation ||= instance if ExpectationChain === instance
|
68
|
+
if ExpectationChain === instance && !@instance_with_expectation.equal?(instance)
|
54
69
|
raise RSpec::Mocks::MockExpectationError, "Exactly one instance should have received the following message(s) but didn't: #{unfulfilled_expectations.sort.join(', ')}"
|
55
70
|
end
|
56
71
|
end
|
@@ -11,7 +11,7 @@ module RSpec
|
|
11
11
|
# @see Chain
|
12
12
|
class Recorder
|
13
13
|
# @private
|
14
|
-
attr_reader :message_chains, :stubs
|
14
|
+
attr_reader :message_chains, :stubs, :klass
|
15
15
|
|
16
16
|
def initialize(klass)
|
17
17
|
@message_chains = MessageChains.new
|
@@ -27,7 +27,7 @@ module RSpec
|
|
27
27
|
#
|
28
28
|
# @see Methods#stub
|
29
29
|
def stub(method_name_or_method_map, &block)
|
30
|
-
if method_name_or_method_map
|
30
|
+
if Hash === method_name_or_method_map
|
31
31
|
method_name_or_method_map.each do |method_name, return_value|
|
32
32
|
stub(method_name).and_return(return_value)
|
33
33
|
end
|
@@ -57,7 +57,7 @@ module RSpec
|
|
57
57
|
def should_receive(method_name, &block)
|
58
58
|
@expectation_set = true
|
59
59
|
observe!(method_name)
|
60
|
-
message_chains.add(method_name,
|
60
|
+
message_chains.add(method_name, PositiveExpectationChain.new(self, method_name, &block))
|
61
61
|
end
|
62
62
|
|
63
63
|
def should_not_receive(method_name, &block)
|
@@ -88,16 +88,9 @@ module RSpec
|
|
88
88
|
if @expectation_set && !message_chains.all_expectations_fulfilled?
|
89
89
|
raise RSpec::Mocks::MockExpectationError, "Exactly one instance should have received the following message(s) but didn't: #{message_chains.unfulfilled_expectations.sort.join(', ')}"
|
90
90
|
end
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
def stub!(*)
|
95
|
-
raise "stub! is not supported on any_instance. Use stub instead."
|
96
|
-
end
|
97
|
-
|
98
|
-
# @private
|
99
|
-
def unstub!(*)
|
100
|
-
raise "unstub! is not supported on any_instance. Use unstub instead."
|
91
|
+
ensure
|
92
|
+
stop_all_observation!
|
93
|
+
::RSpec::Mocks.space.remove_any_instance_recorder_for(@klass)
|
101
94
|
end
|
102
95
|
|
103
96
|
# @private
|
@@ -149,7 +142,7 @@ module RSpec
|
|
149
142
|
|
150
143
|
def restore_original_method!(method_name)
|
151
144
|
alias_method_name = build_alias_method_name(method_name)
|
152
|
-
@klass.
|
145
|
+
@klass.class_exec do
|
153
146
|
remove_method method_name
|
154
147
|
alias_method method_name, alias_method_name
|
155
148
|
remove_method alias_method_name
|
@@ -157,14 +150,14 @@ module RSpec
|
|
157
150
|
end
|
158
151
|
|
159
152
|
def remove_dummy_method!(method_name)
|
160
|
-
@klass.
|
153
|
+
@klass.class_exec do
|
161
154
|
remove_method method_name
|
162
155
|
end
|
163
156
|
end
|
164
157
|
|
165
158
|
def backup_method!(method_name)
|
166
159
|
alias_method_name = build_alias_method_name(method_name)
|
167
|
-
@klass.
|
160
|
+
@klass.class_exec do
|
168
161
|
alias_method alias_method_name, method_name
|
169
162
|
end if public_protected_or_private_method_defined?(method_name)
|
170
163
|
end
|
@@ -179,28 +172,27 @@ module RSpec
|
|
179
172
|
end
|
180
173
|
|
181
174
|
def observe!(method_name)
|
175
|
+
if RSpec::Mocks.configuration.verify_partial_doubles?
|
176
|
+
raise MockExpectationError unless @klass.method_defined?(method_name)
|
177
|
+
end
|
178
|
+
|
182
179
|
stop_observing!(method_name) if already_observing?(method_name)
|
183
180
|
@observed_methods << method_name
|
184
181
|
backup_method!(method_name)
|
185
|
-
@klass.
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
end
|
191
|
-
EOM
|
182
|
+
@klass.__send__(:define_method, method_name) do |*args, &blk|
|
183
|
+
klass = ::RSpec::Mocks.method_handle_for(self, method_name).owner
|
184
|
+
::RSpec::Mocks.any_instance_recorder_for(klass).playback!(self, method_name)
|
185
|
+
self.__send__(method_name, *args, &blk)
|
186
|
+
end
|
192
187
|
end
|
193
188
|
|
194
189
|
def mark_invoked!(method_name)
|
195
190
|
backup_method!(method_name)
|
196
|
-
@klass.
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
raise RSpec::Mocks::MockExpectationError, "The message '#{method_name}' was received by \#{self.inspect} but has already been received by \#{invoked_instance}"
|
202
|
-
end
|
203
|
-
EOM
|
191
|
+
@klass.__send__(:define_method, method_name) do |*args, &blk|
|
192
|
+
klass = ::RSpec::Mocks.method_handle_for(self, method_name).owner
|
193
|
+
invoked_instance = ::RSpec::Mocks.any_instance_recorder_for(klass).instance_that_received(method_name)
|
194
|
+
raise RSpec::Mocks::MockExpectationError, "The message '#{method_name}' was received by #{self.inspect} but has already been received by #{invoked_instance}"
|
195
|
+
end
|
204
196
|
end
|
205
197
|
end
|
206
198
|
end
|