rspec-mocks 2.99.4 → 3.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|