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.
Files changed (133) hide show
  1. checksums.yaml +14 -6
  2. checksums.yaml.gz.sig +2 -0
  3. data.tar.gz.sig +1 -0
  4. data/Changelog.md +89 -105
  5. data/License.txt +1 -0
  6. data/README.md +77 -57
  7. data/features/argument_matchers/explicit.feature +5 -5
  8. data/features/argument_matchers/general_matchers.feature +10 -10
  9. data/features/argument_matchers/type_matchers.feature +3 -3
  10. data/features/message_expectations/allow_any_instance_of.feature +1 -1
  11. data/features/message_expectations/any_instance.feature +27 -5
  12. data/features/message_expectations/call_original.feature +2 -2
  13. data/features/message_expectations/expect_message_using_expect.feature +2 -2
  14. data/features/message_expectations/expect_message_using_should_receive.feature +2 -2
  15. data/features/message_expectations/receive_counts.feature +7 -7
  16. data/features/message_expectations/warn_when_expectation_is_set_on_nil.feature +3 -3
  17. data/features/method_stubs/README.md +3 -0
  18. data/features/method_stubs/any_instance.feature +11 -11
  19. data/features/method_stubs/as_null_object.feature +4 -4
  20. data/features/method_stubs/simple_return_value_with_stub.feature +7 -7
  21. data/features/method_stubs/stub_chain.feature +3 -3
  22. data/features/method_stubs/stub_implementation.feature +2 -2
  23. data/features/method_stubs/to_ary.feature +2 -2
  24. data/features/mutating_constants/hiding_defined_constant.feature +2 -2
  25. data/features/mutating_constants/stub_defined_constant.feature +5 -5
  26. data/features/mutating_constants/stub_undefined_constant.feature +6 -6
  27. data/features/outside_rspec/configuration.feature +0 -2
  28. data/features/outside_rspec/standalone.feature +1 -1
  29. data/features/spies/spy_partial_mock_method.feature +2 -2
  30. data/features/spies/spy_pure_mock_method.feature +5 -5
  31. data/features/spies/spy_unstubbed_method.feature +1 -1
  32. data/features/support/env.rb +10 -1
  33. data/features/test_frameworks/test_unit.feature +1 -1
  34. data/features/verifying_doubles/class_doubles.feature +88 -0
  35. data/features/verifying_doubles/dynamic_classes.feature +72 -0
  36. data/features/verifying_doubles/introduction.feature +85 -0
  37. data/features/verifying_doubles/object_doubles.feature +65 -0
  38. data/features/verifying_doubles/partial_doubles.feature +34 -0
  39. data/lib/rspec/mocks.rb +8 -34
  40. data/lib/rspec/mocks/any_instance/chain.rb +4 -34
  41. data/lib/rspec/mocks/any_instance/expectation_chain.rb +14 -4
  42. data/lib/rspec/mocks/any_instance/message_chains.rb +27 -12
  43. data/lib/rspec/mocks/any_instance/recorder.rb +23 -31
  44. data/lib/rspec/mocks/any_instance/stub_chain.rb +9 -4
  45. data/lib/rspec/mocks/argument_list_matcher.rb +8 -1
  46. data/lib/rspec/mocks/argument_matchers.rb +26 -12
  47. data/lib/rspec/mocks/arity_calculator.rb +66 -0
  48. data/lib/rspec/mocks/configuration.rb +42 -14
  49. data/lib/rspec/mocks/error_generator.rb +34 -10
  50. data/lib/rspec/mocks/example_methods.rb +64 -19
  51. data/lib/rspec/mocks/extensions/marshal.rb +0 -15
  52. data/lib/rspec/mocks/framework.rb +4 -4
  53. data/lib/rspec/mocks/instance_method_stasher.rb +80 -62
  54. data/lib/rspec/mocks/matchers/have_received.rb +18 -14
  55. data/lib/rspec/mocks/matchers/receive.rb +29 -7
  56. data/lib/rspec/mocks/matchers/receive_messages.rb +72 -0
  57. data/lib/rspec/mocks/message_expectation.rb +95 -148
  58. data/lib/rspec/mocks/method_double.rb +77 -139
  59. data/lib/rspec/mocks/method_reference.rb +95 -0
  60. data/lib/rspec/mocks/mock.rb +1 -1
  61. data/lib/rspec/mocks/mutate_const.rb +12 -9
  62. data/lib/rspec/mocks/object_reference.rb +90 -0
  63. data/lib/rspec/mocks/order_group.rb +49 -7
  64. data/lib/rspec/mocks/proxy.rb +72 -33
  65. data/lib/rspec/mocks/proxy_for_nil.rb +2 -2
  66. data/lib/rspec/mocks/space.rb +13 -18
  67. data/lib/rspec/mocks/stub_chain.rb +2 -2
  68. data/lib/rspec/mocks/syntax.rb +61 -36
  69. data/lib/rspec/mocks/targets.rb +40 -19
  70. data/lib/rspec/mocks/test_double.rb +12 -56
  71. data/lib/rspec/mocks/verifying_double.rb +77 -0
  72. data/lib/rspec/mocks/verifying_message_expecation.rb +60 -0
  73. data/lib/rspec/mocks/verifying_proxy.rb +151 -0
  74. data/lib/rspec/mocks/version.rb +1 -1
  75. data/spec/rspec/mocks/and_call_original_spec.rb +34 -30
  76. data/spec/rspec/mocks/and_yield_spec.rb +2 -2
  77. data/spec/rspec/mocks/any_instance/message_chains_spec.rb +1 -1
  78. data/spec/rspec/mocks/any_instance_spec.rb +53 -260
  79. data/spec/rspec/mocks/argument_expectation_spec.rb +4 -4
  80. data/spec/rspec/mocks/arity_calculator_spec.rb +95 -0
  81. data/spec/rspec/mocks/array_including_matcher_spec.rb +41 -0
  82. data/spec/rspec/mocks/at_least_spec.rb +4 -32
  83. data/spec/rspec/mocks/block_return_value_spec.rb +4 -135
  84. data/spec/rspec/mocks/combining_implementation_instructions_spec.rb +10 -11
  85. data/spec/rspec/mocks/configuration_spec.rb +79 -0
  86. data/spec/rspec/mocks/double_spec.rb +10 -78
  87. data/spec/rspec/mocks/extensions/marshal_spec.rb +0 -8
  88. data/spec/rspec/mocks/failing_argument_matchers_spec.rb +49 -4
  89. data/spec/rspec/mocks/instance_method_stasher_spec.rb +20 -3
  90. data/spec/rspec/mocks/matchers/have_received_spec.rb +74 -0
  91. data/spec/rspec/mocks/matchers/receive_messages_spec.rb +140 -0
  92. data/spec/rspec/mocks/matchers/receive_spec.rb +82 -42
  93. data/spec/rspec/mocks/methods_spec.rb +1 -1
  94. data/spec/rspec/mocks/{bug_report_830_spec.rb → mock_expectation_error_spec.rb} +4 -3
  95. data/spec/rspec/mocks/mock_ordering_spec.rb +11 -0
  96. data/spec/rspec/mocks/mock_space_spec.rb +10 -1
  97. data/spec/rspec/mocks/mock_spec.rb +26 -82
  98. data/spec/rspec/mocks/multiple_return_value_spec.rb +1 -1
  99. data/spec/rspec/mocks/mutate_const_spec.rb +18 -5
  100. data/spec/rspec/mocks/null_object_mock_spec.rb +6 -4
  101. data/spec/rspec/mocks/options_hash_spec.rb +3 -3
  102. data/spec/rspec/mocks/order_group_spec.rb +27 -0
  103. data/spec/rspec/mocks/partial_mock_spec.rb +101 -1
  104. data/spec/rspec/mocks/passing_argument_matchers_spec.rb +3 -20
  105. data/spec/rspec/mocks/record_messages_spec.rb +4 -4
  106. data/spec/rspec/mocks/serialization_spec.rb +4 -6
  107. data/spec/rspec/mocks/space_spec.rb +3 -3
  108. data/spec/rspec/mocks/stub_chain_spec.rb +0 -12
  109. data/spec/rspec/mocks/stub_spec.rb +23 -44
  110. data/spec/rspec/mocks/test_double_spec.rb +3 -22
  111. data/spec/rspec/mocks/verifying_double_spec.rb +327 -0
  112. data/spec/rspec/mocks/verifying_message_expecation_spec.rb +68 -0
  113. data/spec/rspec/mocks_spec.rb +16 -39
  114. data/spec/spec_helper.rb +29 -18
  115. metadata +131 -86
  116. metadata.gz.sig +1 -0
  117. data/features/message_expectations/expect_any_instance_of.feature +0 -27
  118. data/lib/rspec/mocks/caller_filter.rb +0 -60
  119. data/lib/rspec/mocks/deprecation.rb +0 -26
  120. data/lib/rspec/mocks/extensions/instance_exec.rb +0 -34
  121. data/lib/rspec/mocks/extensions/proc.rb +0 -63
  122. data/lib/spec/mocks.rb +0 -4
  123. data/spec/rspec/mocks/and_return_spec.rb +0 -17
  124. data/spec/rspec/mocks/any_number_of_times_spec.rb +0 -36
  125. data/spec/rspec/mocks/before_all_spec.rb +0 -74
  126. data/spec/rspec/mocks/bug_report_10260_spec.rb +0 -8
  127. data/spec/rspec/mocks/bug_report_10263_spec.rb +0 -27
  128. data/spec/rspec/mocks/bug_report_11545_spec.rb +0 -32
  129. data/spec/rspec/mocks/bug_report_496_spec.rb +0 -17
  130. data/spec/rspec/mocks/bug_report_600_spec.rb +0 -22
  131. data/spec/rspec/mocks/bug_report_7611_spec.rb +0 -16
  132. data/spec/rspec/mocks/bug_report_8165_spec.rb +0 -31
  133. data/spec/rspec/mocks/bug_report_957_spec.rb +0 -22
@@ -0,0 +1,60 @@
1
+ require 'rspec/mocks/arity_calculator'
2
+
3
+ module RSpec
4
+ module Mocks
5
+
6
+ # A message expectation that knows about the real implementation of the
7
+ # message being expected, so that it can verify that any expectations
8
+ # have the correct arity.
9
+ class VerifyingMessageExpectation < MessageExpectation
10
+
11
+ # A level of indirection is used here rather than just passing in the
12
+ # method itself, since method look up is expensive and we only want to
13
+ # do it if actually needed.
14
+ #
15
+ # Conceptually the method reference makes more sense as a constructor
16
+ # argument since it should be immutable, but it is significantly more
17
+ # straight forward to build the object in pieces so for now it stays as
18
+ # an accessor.
19
+ attr_accessor :method_reference
20
+
21
+ def initialize(*args)
22
+ super
23
+ end
24
+
25
+ # @override
26
+ def with(*args, &block)
27
+ unless ArgumentMatchers::AnyArgsMatcher === args.first
28
+ expected_arity = if ArgumentMatchers::NoArgsMatcher === args.first
29
+ 0
30
+ elsif args.length > 0
31
+ args.length
32
+ else
33
+ # No arguments given, this will raise.
34
+ super
35
+ end
36
+
37
+ ensure_arity!(expected_arity)
38
+ end
39
+ super
40
+ end
41
+
42
+ private
43
+
44
+ def ensure_arity!(actual)
45
+ return if method_reference.nil?
46
+
47
+ method_reference.when_defined do |method|
48
+ calculator = ArityCalculator.new(method)
49
+ unless calculator.within_range?(actual)
50
+ # Fail fast is required, otherwise the message expecation will fail
51
+ # as well ("expected method not called") and clobber this one.
52
+ @failed_fast = true
53
+ @error_generator.raise_arity_error(calculator, actual)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+
@@ -0,0 +1,151 @@
1
+ require 'rspec/mocks/verifying_message_expecation'
2
+ require 'rspec/mocks/method_reference'
3
+
4
+ module RSpec
5
+ module Mocks
6
+
7
+ module VerifyingProxyMethods
8
+ def add_stub(location, method_name, opts={}, &implementation)
9
+ ensure_implemented(method_name)
10
+ super
11
+ end
12
+
13
+ def add_simple_stub(method_name, *args)
14
+ ensure_implemented(method_name)
15
+ super
16
+ end
17
+
18
+ def add_message_expectation(location, method_name, opts={}, &block)
19
+ ensure_implemented(method_name)
20
+ super
21
+ end
22
+
23
+ def ensure_implemented(method_name)
24
+ return unless @doubled_module.defined?
25
+
26
+ method_reference[method_name].when_unimplemented do
27
+ @error_generator.raise_unimplemented_error(
28
+ @doubled_module,
29
+ method_name
30
+ )
31
+ end
32
+ end
33
+ end
34
+
35
+ # A verifying proxy mostly acts like a normal proxy, except that it
36
+ # contains extra logic to try and determine the validity of any expectation
37
+ # set on it. This includes whether or not methods have been defined and the
38
+ # arity of method calls.
39
+ #
40
+ # In all other ways this behaves like a normal proxy. It only adds the
41
+ # verification behaviour to specific methods then delegates to the parent
42
+ # implementation.
43
+ #
44
+ # These checks are only activated if the doubled class has already been
45
+ # loaded, otherwise they are disabled. This allows for testing in
46
+ # isolation.
47
+ #
48
+ # @api private
49
+ class VerifyingProxy < Proxy
50
+ include VerifyingProxyMethods
51
+
52
+ def initialize(object, order_group, name, method_reference_class)
53
+ super(object, order_group)
54
+ @object = object
55
+ @doubled_module = name
56
+ @method_reference_class = method_reference_class
57
+
58
+ # A custom method double is required to pass through a way to lookup
59
+ # methods to determine their arity. This is only relevant if the doubled
60
+ # class is loaded.
61
+ @method_doubles = Hash.new do |h, k|
62
+ h[k] = VerifyingMethodDouble.new(@object, k, self, method_reference[k])
63
+ end
64
+ end
65
+
66
+ def method_reference
67
+ @method_reference ||= Hash.new do |h, k|
68
+ h[k] = @method_reference_class.new(@doubled_module, k)
69
+ end
70
+ end
71
+ end
72
+
73
+ class VerifyingPartialMockProxy < PartialMockProxy
74
+ include VerifyingProxyMethods
75
+
76
+ def initialize(object, expectation_ordering)
77
+ super(object, expectation_ordering)
78
+ @doubled_module = DirectObjectReference.new(object)
79
+
80
+ # A custom method double is required to pass through a way to lookup
81
+ # methods to determine their arity.
82
+ @method_doubles = Hash.new do |h, k|
83
+ h[k] = VerifyingExistingMethodDouble.new(object, k, self)
84
+ end
85
+ end
86
+
87
+ def method_reference
88
+ @method_doubles
89
+ end
90
+ end
91
+
92
+ # @api private
93
+ class VerifyingMethodDouble < MethodDouble
94
+ def initialize(object, method_name, proxy, method_reference)
95
+ super(object, method_name, proxy)
96
+ @method_reference = method_reference
97
+ end
98
+
99
+ def message_expectation_class
100
+ VerifyingMessageExpectation
101
+ end
102
+
103
+ def add_expectation(*arg)
104
+ super.tap { |x| x.method_reference = @method_reference }
105
+ end
106
+
107
+ def proxy_method_invoked(obj, *args, &block)
108
+ ensure_arity!(args.length)
109
+ super
110
+ end
111
+
112
+ private
113
+
114
+ def ensure_arity!(arity)
115
+ @method_reference.when_defined do |method|
116
+ calculator = ArityCalculator.new(method)
117
+ unless calculator.within_range?(arity)
118
+ raise ArgumentError, "wrong number of arguments (#{arity} for #{method.arity})"
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ # @api private
125
+ #
126
+ # A VerifyingMethodDouble fetches the method to verify against from the
127
+ # original object, using a MethodReference. This works for pure doubles,
128
+ # but when the original object is itself the one being modified we need to
129
+ # collapse the reference and the method double into a single object so that
130
+ # we can access the original pristine method definition.
131
+ class VerifyingExistingMethodDouble < VerifyingMethodDouble
132
+ def initialize(object, method_name, proxy)
133
+ super(object, method_name, proxy, self)
134
+
135
+ @valid_method = object.respond_to?(method_name)
136
+
137
+ # Trigger an eager find of the original method since if we find it any
138
+ # later we end up getting a stubbed method with incorrect arity.
139
+ save_original_method!
140
+ end
141
+
142
+ def when_defined
143
+ yield original_method
144
+ end
145
+
146
+ def when_unimplemented
147
+ yield unless @valid_method
148
+ end
149
+ end
150
+ end
151
+ end
@@ -1,7 +1,7 @@
1
1
  module RSpec
2
2
  module Mocks
3
3
  module Version
4
- STRING = '2.99.4'
4
+ STRING = '3.0.0.beta1'
5
5
  end
6
6
  end
7
7
  end
@@ -22,24 +22,36 @@ describe "and_call_original" do
22
22
  let(:instance) { klass.new }
23
23
 
24
24
  it 'passes the received message through to the original method' do
25
+ expect(instance).to receive(:meth_1).and_call_original
26
+ expect(instance.meth_1).to eq(:original)
27
+ end
28
+
29
+ it 'ignores prior declared stubs' do
30
+ instance.stub(:meth_1).and_return(:stubbed_value)
25
31
  instance.should_receive(:meth_1).and_call_original
26
32
  expect(instance.meth_1).to eq(:original)
27
33
  end
28
34
 
29
35
  it 'passes args and blocks through to the original method' do
30
- instance.should_receive(:meth_2).and_call_original
36
+ expect(instance).to receive(:meth_2).and_call_original
31
37
  value = instance.meth_2(:submitted_arg) { |a, b| [a, b] }
32
38
  expect(value).to eq([:submitted_arg, :additional_yielded_arg])
33
39
  end
34
40
 
35
41
  it 'errors when you pass through the wrong number of args' do
36
- instance.stub(:meth_1).and_call_original
37
- instance.stub(:meth_2).and_call_original
42
+ expect(instance).to receive(:meth_1).and_call_original
43
+ expect(instance).to receive(:meth_2).twice.and_call_original
38
44
  expect { instance.meth_1 :a }.to raise_error ArgumentError
39
45
  expect { instance.meth_2 {} }.to raise_error ArgumentError
40
46
  expect { instance.meth_2(:a, :b) {} }.to raise_error ArgumentError
41
47
  end
42
48
 
49
+ it 'warns when you override an existing implementation' do
50
+ expect(RSpec).to receive(:warning).with(/overriding a previous implementation/)
51
+ expect(instance).to receive(:meth_1) { true }.and_call_original
52
+ instance.meth_1
53
+ end
54
+
43
55
  context "for singleton methods" do
44
56
  it 'works' do
45
57
  def instance.foo; :bar; end
@@ -77,6 +89,15 @@ describe "and_call_original" do
77
89
  expect(sub_klass.foo).to eq(:sub_klass_bar)
78
90
  end
79
91
 
92
+ it "finds the method on the most direct singleton class ancestors even if the method " +
93
+ "is available on more distant ancestors" do
94
+ klass.extend Module.new { def foo; :klass_bar; end }
95
+ sub_klass = Class.new(klass) { def self.foo; :sub_klass_bar; end }
96
+ sub_sub_klass = Class.new(sub_klass)
97
+ sub_sub_klass.should_receive(:foo).and_call_original
98
+ expect(sub_sub_klass.foo).to eq(:sub_klass_bar)
99
+ end
100
+
80
101
  context 'when using any_instance' do
81
102
  it 'works for instance methods defined on the class' do
82
103
  klass.any_instance.should_receive(:meth_1).and_call_original
@@ -95,33 +116,16 @@ describe "and_call_original" do
95
116
  end
96
117
  end
97
118
 
98
- if RUBY_VERSION.to_f > 1.8
99
- it 'works for class methods defined on a superclass' do
100
- subclass = Class.new(klass)
101
- subclass.should_receive(:new_instance).and_call_original
102
- expect(subclass.new_instance).to be_a(subclass)
103
- end
104
-
105
- it 'works for class methods defined on a grandparent class' do
106
- sub_subclass = Class.new(Class.new(klass))
107
- sub_subclass.should_receive(:new_instance).and_call_original
108
- expect(sub_subclass.new_instance).to be_a(sub_subclass)
109
- end
110
- else
111
- it 'attempts to work for class methods defined on a superclass but ' +
112
- 'executes the method with `self` as the superclass' do
113
- ::Kernel.stub(:warn)
114
- subclass = Class.new(klass)
115
- subclass.should_receive(:new_instance).and_call_original
116
- expect(subclass.new_instance).to be_an_instance_of(klass)
117
- end
119
+ it 'works for class methods defined on a superclass' do
120
+ subclass = Class.new(klass)
121
+ subclass.should_receive(:new_instance).and_call_original
122
+ expect(subclass.new_instance).to be_a(subclass)
123
+ end
118
124
 
119
- it 'prints a warning to notify users that `self` will not be correct' do
120
- subclass = Class.new(klass)
121
- ::Kernel.should_receive(:warn).with(/may not work correctly/)
122
- subclass.should_receive(:new_instance).and_call_original
123
- subclass.new_instance
124
- end
125
+ it 'works for class methods defined on a grandparent class' do
126
+ sub_subclass = Class.new(Class.new(klass))
127
+ sub_subclass.should_receive(:new_instance).and_call_original
128
+ expect(sub_subclass.new_instance).to be_a(sub_subclass)
125
129
  end
126
130
 
127
131
  it 'works for class methods defined on the Class class' do
@@ -149,7 +153,7 @@ describe "and_call_original" do
149
153
 
150
154
  context 'on an object that defines method_missing' do
151
155
  before do
152
- klass.class_eval do
156
+ klass.class_exec do
153
157
  private
154
158
 
155
159
  def method_missing(name, *args)
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe RSpec::Mocks::Double do
3
+ describe RSpec::Mocks::Mock do
4
4
 
5
5
  let(:obj) { double }
6
6
 
@@ -25,7 +25,7 @@ describe RSpec::Mocks::Double do
25
25
  obj.stub(:method_that_accepts_a_block).and_yield do |eval_context|
26
26
  evaluated = true
27
27
  end
28
- expect(evaluated).to be true
28
+ expect(evaluated).to be_truthy
29
29
  end
30
30
 
31
31
  it "passes an eval context object to the supplied block" do
@@ -4,7 +4,7 @@ describe RSpec::Mocks::AnyInstance::MessageChains do
4
4
  let(:recorder) { double }
5
5
  let(:chains) { RSpec::Mocks::AnyInstance::MessageChains.new }
6
6
  let(:stub_chain) { RSpec::Mocks::AnyInstance::StubChain.new recorder }
7
- let(:expectation_chain) { RSpec::Mocks::AnyInstance::ExpectationChain.new recorder }
7
+ let(:expectation_chain) { RSpec::Mocks::AnyInstance::PositiveExpectationChain.new recorder }
8
8
 
9
9
  it "knows if a method does not have an expectation set on it" do
10
10
  chains.add(:method_name, stub_chain)
@@ -37,7 +37,7 @@ module RSpec
37
37
  end
38
38
 
39
39
  context "#stub_chain" do
40
- it "raises an error if 'stub_chain' follows 'any_instance'" do
40
+ it "raises an error if 'stub_chain' follows 'and_return'" do
41
41
  expect { klass.any_instance.and_return("1").stub_chain(:foo, :bar) }.to raise_error(NoMethodError)
42
42
  end
43
43
  end
@@ -48,12 +48,12 @@ module RSpec
48
48
  end
49
49
 
50
50
  it "raises an error if 'with' follows 'and_return'" do
51
- skip "see Github issue #42"
51
+ pending "see Github issue #42"
52
52
  expect { klass.any_instance.should_receive(:foo).and_return(1).with("1") }.to raise_error(NoMethodError)
53
53
  end
54
54
 
55
55
  it "raises an error if 'with' follows 'and_raise'" do
56
- skip "see Github issue #42"
56
+ pending "see Github issue #42"
57
57
  expect { klass.any_instance.should_receive(:foo).and_raise(1).with("1") }.to raise_error(NoMethodError)
58
58
  end
59
59
  end
@@ -214,8 +214,6 @@ module RSpec
214
214
  end
215
215
 
216
216
  context "with a block" do
217
- before { allow_unavoidable_1_8_deprecation }
218
-
219
217
  it "stubs a method" do
220
218
  klass.any_instance.stub(:foo) { 1 }
221
219
  expect(klass.new.foo).to eq(1)
@@ -227,6 +225,24 @@ module RSpec
227
225
  end
228
226
  end
229
227
 
228
+ context "when partially mocking objects" do
229
+ let(:obj) { klass.new }
230
+
231
+ it "resets partially mocked objects correctly" do
232
+ allow_any_instance_of(klass).to receive(:existing_method).and_return("stubbed value")
233
+
234
+ # Simply resetting the proxy doesn't work
235
+ # what we need to have happen is
236
+ # ::RSpec::Mocks.any_instance_recorder_for(klass).stop_all_observation!
237
+ # but that is never invoked in ::
238
+ expect {
239
+ RSpec::Mocks.space.verify_all
240
+ }.to(
241
+ change { obj.existing_method }.from("stubbed value").to(:existing_method_return_value)
242
+ )
243
+ end
244
+ end
245
+
230
246
  context "core ruby objects" do
231
247
  it "works uniformly across *everything*" do
232
248
  Object.any_instance.stub(:foo).and_return(1)
@@ -267,22 +283,6 @@ module RSpec
267
283
  end
268
284
  end
269
285
 
270
- context "with #stub!" do
271
- it "raises with a message instructing the user to use stub instead" do
272
- expect do
273
- klass.any_instance.stub!(:foo)
274
- end.to raise_error(/Use stub instead/)
275
- end
276
- end
277
-
278
- context "with #unstub!" do
279
- it "raises with a message instructing the user to use unstub instead" do
280
- expect do
281
- klass.any_instance.unstub!(:foo)
282
- end.to raise_error(/Use unstub instead/)
283
- end
284
- end
285
-
286
286
  context "unstub implementation" do
287
287
  it "replaces the stubbed method with the original method" do
288
288
  klass.any_instance.stub(:existing_method)
@@ -377,7 +377,6 @@ module RSpec
377
377
  klass.any_instance.should_not_receive(:bar)
378
378
  klass.new.foo
379
379
  RSpec::Mocks.space.verify_all
380
- RSpec::Mocks.space.reset_all
381
380
  end
382
381
  end
383
382
 
@@ -400,36 +399,24 @@ module RSpec
400
399
 
401
400
  it "fails if an instance is created but no invocation occurs" do
402
401
  expect do
403
- begin
404
- klass.any_instance.should_receive(:foo)
405
- klass.new
406
- RSpec::Mocks.space.verify_all
407
- ensure
408
- RSpec::Mocks.space.reset_all
409
- end
402
+ klass.any_instance.should_receive(:foo)
403
+ klass.new
404
+ RSpec::Mocks.space.verify_all
410
405
  end.to raise_error(RSpec::Mocks::MockExpectationError, foo_expectation_error_message)
411
406
  end
412
407
 
413
408
  it "fails if no instance is created" do
414
409
  expect do
415
- begin
416
- klass.any_instance.should_receive(:foo).and_return(1)
417
- RSpec::Mocks.space.verify_all
418
- ensure
419
- RSpec::Mocks.space.reset_all
420
- end
410
+ klass.any_instance.should_receive(:foo).and_return(1)
411
+ RSpec::Mocks.space.verify_all
421
412
  end.to raise_error(RSpec::Mocks::MockExpectationError, foo_expectation_error_message)
422
413
  end
423
414
 
424
415
  it "fails if no instance is created and there are multiple expectations" do
425
416
  expect do
426
- begin
427
- klass.any_instance.should_receive(:foo)
428
- klass.any_instance.should_receive(:bar)
429
- RSpec::Mocks.space.verify_all
430
- ensure
431
- RSpec::Mocks.space.reset_all
432
- end
417
+ klass.any_instance.should_receive(:foo)
418
+ klass.any_instance.should_receive(:bar)
419
+ RSpec::Mocks.space.verify_all
433
420
  end.to raise_error(RSpec::Mocks::MockExpectationError, 'Exactly one instance should have received the following message(s) but didn\'t: bar, foo')
434
421
  end
435
422
 
@@ -491,36 +478,24 @@ module RSpec
491
478
 
492
479
  it "fails if an instance is created but no invocation occurs" do
493
480
  expect do
494
- begin
495
- klass.any_instance.should_receive(:existing_method)
496
- klass.new
497
- RSpec::Mocks.space.verify_all
498
- ensure
499
- RSpec::Mocks.space.reset_all
500
- end
481
+ klass.any_instance.should_receive(:existing_method)
482
+ klass.new
483
+ RSpec::Mocks.space.verify_all
501
484
  end.to raise_error(RSpec::Mocks::MockExpectationError, existing_method_expectation_error_message)
502
485
  end
503
486
 
504
487
  it "fails if no instance is created" do
505
488
  expect do
506
- begin
507
- klass.any_instance.should_receive(:existing_method)
508
- RSpec::Mocks.space.verify_all
509
- ensure
510
- RSpec::Mocks.space.reset_all
511
- end
489
+ klass.any_instance.should_receive(:existing_method)
490
+ RSpec::Mocks.space.verify_all
512
491
  end.to raise_error(RSpec::Mocks::MockExpectationError, existing_method_expectation_error_message)
513
492
  end
514
493
 
515
494
  it "fails if no instance is created and there are multiple expectations" do
516
495
  expect do
517
- begin
518
- klass.any_instance.should_receive(:existing_method)
519
- klass.any_instance.should_receive(:another_existing_method)
520
- RSpec::Mocks.space.verify_all
521
- ensure
522
- RSpec::Mocks.space.reset_all
523
- end
496
+ klass.any_instance.should_receive(:existing_method)
497
+ klass.any_instance.should_receive(:another_existing_method)
498
+ RSpec::Mocks.space.verify_all
524
499
  end.to raise_error(RSpec::Mocks::MockExpectationError, 'Exactly one instance should have received the following message(s) but didn\'t: another_existing_method, existing_method')
525
500
  end
526
501
 
@@ -613,24 +588,16 @@ module RSpec
613
588
 
614
589
  it "fails when no instances are declared" do
615
590
  expect do
616
- begin
617
- klass.any_instance.should_receive(:foo).once
618
- RSpec::Mocks.space.verify_all
619
- ensure
620
- RSpec::Mocks.space.reset_all
621
- end
591
+ klass.any_instance.should_receive(:foo).once
592
+ RSpec::Mocks.space.verify_all
622
593
  end.to raise_error(RSpec::Mocks::MockExpectationError, foo_expectation_error_message)
623
594
  end
624
595
 
625
596
  it "fails when an instance is declared but there are no invocations" do
626
597
  expect do
627
- begin
628
- klass.any_instance.should_receive(:foo).once
629
- klass.new
630
- RSpec::Mocks.space.verify_all
631
- ensure
632
- RSpec::Mocks.space.reset_all
633
- end
598
+ klass.any_instance.should_receive(:foo).once
599
+ klass.new
600
+ RSpec::Mocks.space.verify_all
634
601
  end.to raise_error(RSpec::Mocks::MockExpectationError, foo_expectation_error_message)
635
602
  end
636
603
 
@@ -755,55 +722,9 @@ module RSpec
755
722
 
756
723
  it "fails when the other expecations are not met" do
757
724
  expect do
758
- begin
759
- klass.any_instance.should_receive(:foo).never
760
- klass.any_instance.should_receive(:existing_method).and_return(5)
761
- RSpec::Mocks.space.verify_all
762
- ensure
763
- RSpec::Mocks.space.reset_all
764
- end
765
- end.to raise_error(RSpec::Mocks::MockExpectationError, existing_method_expectation_error_message)
766
- end
767
- end
768
- end
769
-
770
- context "the 'any_number_of_times' constraint" do
771
- it "passes for 0 invocations" do
772
- klass.any_instance.should_receive(:foo).any_number_of_times
773
- verify klass.new
774
- end
775
-
776
- it "passes for a non-zero number of invocations" do
777
- allow(RSpec).to receive(:deprecate).with("any_number_of_times", :replacement => "stub")
778
-
779
- klass.any_instance.should_receive(:foo).any_number_of_times
780
- instance = klass.new
781
- instance.foo
782
- verify instance
783
- end
784
-
785
- it "does not interfere with other expectations" do
786
- klass.any_instance.should_receive(:foo).any_number_of_times
787
- klass.any_instance.should_receive(:existing_method).and_return(5)
788
- expect(klass.new.existing_method).to eq(5)
789
- end
790
-
791
- context "when combined with other expectations" do
792
- it "passes when the other expecations are met" do
793
- klass.any_instance.should_receive(:foo).any_number_of_times
794
- klass.any_instance.should_receive(:existing_method).and_return(5)
795
- expect(klass.new.existing_method).to eq(5)
796
- end
797
-
798
- it "fails when the other expecations are not met" do
799
- expect do
800
- begin
801
- klass.any_instance.should_receive(:foo).any_number_of_times
802
- klass.any_instance.should_receive(:existing_method).and_return(5)
803
- RSpec::Mocks.space.verify_all
804
- ensure
805
- RSpec::Mocks.space.reset_all
806
- end
725
+ klass.any_instance.should_receive(:foo).never
726
+ klass.any_instance.should_receive(:existing_method).and_return(5)
727
+ RSpec::Mocks.space.verify_all
807
728
  end.to raise_error(RSpec::Mocks::MockExpectationError, existing_method_expectation_error_message)
808
729
  end
809
730
  end
@@ -823,14 +744,13 @@ module RSpec
823
744
  context "public methods" do
824
745
  before(:each) do
825
746
  klass.any_instance.stub(:existing_method).and_return(1)
826
- expect(klass.method_defined?(:__existing_method_without_any_instance__)).to be true
747
+ expect(klass.method_defined?(:__existing_method_without_any_instance__)).to be_truthy
827
748
  end
828
749
 
829
750
  it "restores the class to its original state after each example when no instance is created" do
830
751
  space.verify_all
831
- space.reset_all
832
752
 
833
- expect(klass.method_defined?(:__existing_method_without_any_instance__)).to be false
753
+ expect(klass.method_defined?(:__existing_method_without_any_instance__)).to be_falsey
834
754
  expect(klass.new.existing_method).to eq(existing_method_return_value)
835
755
  end
836
756
 
@@ -838,9 +758,8 @@ module RSpec
838
758
  klass.new.existing_method
839
759
 
840
760
  space.verify_all
841
- space.reset_all
842
761
 
843
- expect(klass.method_defined?(:__existing_method_without_any_instance__)).to be false
762
+ expect(klass.method_defined?(:__existing_method_without_any_instance__)).to be_falsey
844
763
  expect(klass.new.existing_method).to eq(existing_method_return_value)
845
764
  end
846
765
 
@@ -849,9 +768,8 @@ module RSpec
849
768
  klass.new.existing_method
850
769
 
851
770
  space.verify_all
852
- space.reset_all
853
771
 
854
- expect(klass.method_defined?(:__existing_method_without_any_instance__)).to be false
772
+ expect(klass.method_defined?(:__existing_method_without_any_instance__)).to be_falsey
855
773
  expect(klass.new.existing_method).to eq(existing_method_return_value)
856
774
  end
857
775
  end
@@ -860,15 +778,14 @@ module RSpec
860
778
  before :each do
861
779
  klass.any_instance.stub(:private_method).and_return(:something)
862
780
  space.verify_all
863
- space.reset_all
864
781
  end
865
782
 
866
783
  it "cleans up the backed up method" do
867
- expect(klass.method_defined?(:__existing_method_without_any_instance__)).to be false
784
+ expect(klass.method_defined?(:__existing_method_without_any_instance__)).to be_falsey
868
785
  end
869
786
 
870
787
  it "restores a stubbed private method after the spec is run" do
871
- expect(klass.private_method_defined?(:private_method)).to be true
788
+ expect(klass.private_method_defined?(:private_method)).to be_truthy
872
789
  end
873
790
 
874
791
  it "ensures that the restored method behaves as it originally did" do
@@ -883,15 +800,14 @@ module RSpec
883
800
  klass.any_instance.should_receive(:private_method).and_return(:something)
884
801
  klass.new.private_method
885
802
  space.verify_all
886
- space.reset_all
887
803
  end
888
804
 
889
805
  it "cleans up the backed up method" do
890
- expect(klass.method_defined?(:__existing_method_without_any_instance__)).to be false
806
+ expect(klass.method_defined?(:__existing_method_without_any_instance__)).to be_falsey
891
807
  end
892
808
 
893
809
  it "restores a stubbed private method after the spec is run" do
894
- expect(klass.private_method_defined?(:private_method)).to be true
810
+ expect(klass.private_method_defined?(:private_method)).to be_truthy
895
811
  end
896
812
 
897
813
  it "ensures that the restored method behaves as it originally did" do
@@ -931,7 +847,6 @@ module RSpec
931
847
  klass.any_instance.should_receive(:existing_method).and_return(Object.new)
932
848
  klass.new.existing_method
933
849
  space.verify_all
934
- space.reset_all
935
850
 
936
851
  expect(klass.new.existing_method).to eq(existing_method_return_value)
937
852
  end
@@ -944,7 +859,6 @@ module RSpec
944
859
  klass.any_instance.stub(:existing_method).and_return(true)
945
860
 
946
861
  RSpec::Mocks.space.verify_all
947
- RSpec::Mocks.space.reset_all
948
862
  expect(klass.new).to respond_to(:existing_method)
949
863
  expect(klass.new.existing_method).to eq(existing_method_return_value)
950
864
  end
@@ -1034,126 +948,6 @@ module RSpec
1034
948
  end
1035
949
  end
1036
950
  end
1037
-
1038
- context "by default" do
1039
- def block_regex(line)
1040
- /as the first block argument.*#{__FILE__}:#{line}/m
1041
- end
1042
-
1043
- it "is off" do
1044
- expect(RSpec::Mocks.configuration.yield_receiver_to_any_instance_implementation_blocks?).to be false
1045
- end
1046
-
1047
- it "will warn about allowances receiving blocks in 3.0" do
1048
- klass = Struct.new(:bees)
1049
-
1050
- expect(RSpec).to receive(:warn_deprecation).with(block_regex(__LINE__ + 1))
1051
- allow_any_instance_of(klass).to receive(:foo) { |args| }
1052
- klass.new(:faces).foo
1053
- end
1054
-
1055
- it "will warn about expectations receiving blocks in 3.0" do
1056
- klass = Struct.new(:bees)
1057
-
1058
- expect(RSpec).to receive(:warn_deprecation).with(block_regex(__LINE__ + 1))
1059
- expect_any_instance_of(klass).to receive(:foo) { |args| }
1060
- klass.new(:faces).foo
1061
- end
1062
-
1063
- it 'includes the line of the block declaration in the warning, ' +
1064
- 'even when it is different from the `any_instance` line', :unless => (RUBY_VERSION.to_f < 1.9) do
1065
- klass = Class.new
1066
- expect(RSpec).to receive(:warn_deprecation).with(block_regex(__LINE__ + 3))
1067
- stub = klass.any_instance.stub(:foo)
1068
-
1069
- stub.with("bar") { |args| }
1070
- klass.new.foo("bar")
1071
- end
1072
-
1073
- it "will warn about expectations receiving blocks with a times restriction" do
1074
- klass = Struct.new(:bees)
1075
-
1076
- expect(RSpec).to receive(:warn_deprecation).with(block_regex(__LINE__ + 1))
1077
- klass.any_instance.should_receive(:foo).exactly(3).times { |a| :some_return_value }
1078
-
1079
- instance = klass.new(:faces)
1080
- 3.times { instance.foo }
1081
- end
1082
-
1083
- it "will warn about expectations receiving blocks with an argument expectation" do
1084
- klass = Struct.new(:bees)
1085
-
1086
- expect(RSpec).to receive(:warn_deprecation).with(block_regex(__LINE__ + 1))
1087
- klass.any_instance.should_receive(:foo).with(3) { |b| :some_return_value }
1088
-
1089
- instance = klass.new(:faces)
1090
- instance.foo(3)
1091
- end
1092
-
1093
- it "works with a do end style block" do
1094
- klass = Struct.new(:bees)
1095
-
1096
- expect(RSpec).to receive(:warn_deprecation).with(block_regex(__LINE__ + 1))
1097
- klass.any_instance.should_receive(:foo).with(3) do |a|
1098
- :some_return_value
1099
- end
1100
-
1101
- instance = klass.new(:faces)
1102
- instance.foo(3)
1103
- end
1104
-
1105
- it "won't warn if there is no implementation block on an expectation" do
1106
- expect(RSpec).not_to receive(:warn_deprecation)
1107
-
1108
- klass = Struct.new(:bees)
1109
-
1110
- allow_any_instance_of(klass).to receive(:foo)
1111
- klass.new(:faces).foo
1112
- end
1113
-
1114
- it "won't warn if the implementation block ignores arguments", :if => (RUBY_VERSION.to_f > 1.8) do
1115
- expect(RSpec).not_to receive(:warn_deprecation)
1116
-
1117
- klass = Struct.new(:bees)
1118
- allow_any_instance_of(klass).to receive(:foo) { 5 }
1119
- klass.new(:faces).foo
1120
- end
1121
-
1122
- it "warns if the implementation block accepts a splat" do
1123
- klass = Struct.new(:bees)
1124
-
1125
- expect(RSpec).to receive(:warn_deprecation).with(block_regex(__LINE__ + 1))
1126
- allow_any_instance_of(klass).to receive(:foo) { |*a| 5 }
1127
-
1128
- klass.new(:faces).foo
1129
- end
1130
-
1131
- it "warns if it the implementation is a lambda that expects no arguments" do
1132
- klass = Struct.new(:bees)
1133
-
1134
- expect(RSpec).to receive(:warn_deprecation).with(block_regex(__LINE__ + 1))
1135
- allow_any_instance_of(klass).to receive(:foo, &lambda { 5 })
1136
-
1137
- klass.new(:faces).foo
1138
- end
1139
-
1140
- it "will warn about stubs receiving blocks in 3.0" do
1141
- klass = Struct.new(:bees)
1142
-
1143
- expect(RSpec).to receive(:warn_deprecation).with(block_regex(__LINE__ + 1))
1144
- expect_any_instance_of(klass).to receive(:foo) { |args| }
1145
- klass.new(:faces).foo
1146
- end
1147
-
1148
- it "won't warn if there is no implementation block on an stub" do
1149
- expect(RSpec).not_to receive(:warn_deprecation)
1150
-
1151
- klass = Struct.new(:bees)
1152
-
1153
- allow_any_instance_of(klass).to receive(:foo)
1154
- klass.new(:faces).foo
1155
- end
1156
- end
1157
951
  end
1158
952
 
1159
953
  context 'when used in conjunction with a `dup`' do
@@ -1226,7 +1020,6 @@ module RSpec
1226
1020
  expect(instance.existing_method).to eq :stubbed_return_value
1227
1021
 
1228
1022
  RSpec::Mocks.verify
1229
- RSpec::Mocks.teardown
1230
1023
 
1231
1024
  expect(instance.existing_method).to eq :existing_method_return_value
1232
1025
  end