rspec-mocks 3.0.0.beta1 → 3.0.0.beta2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. data.tar.gz.sig +1 -1
  2. data/Changelog.md +95 -3
  3. data/README.md +27 -13
  4. data/features/README.md +15 -7
  5. data/features/argument_matchers/README.md +5 -5
  6. data/features/argument_matchers/explicit.feature +6 -6
  7. data/features/argument_matchers/general_matchers.feature +4 -4
  8. data/features/argument_matchers/type_matchers.feature +2 -2
  9. data/features/message_expectations/README.md +29 -27
  10. data/features/message_expectations/call_original.feature +0 -1
  11. data/features/message_expectations/message_chains_using_expect.feature +49 -0
  12. data/features/method_stubs/README.md +2 -1
  13. data/features/method_stubs/{any_instance.feature → allow_any_instance_of.feature} +12 -12
  14. data/features/method_stubs/{stub_chain.feature → receive_message_chain.feature} +3 -3
  15. data/features/method_stubs/to_ary.feature +1 -1
  16. data/features/mutating_constants/stub_defined_constant.feature +0 -1
  17. data/features/outside_rspec/standalone.feature +1 -1
  18. data/features/spies/spy_pure_mock_method.feature +1 -1
  19. data/features/test_frameworks/test_unit.feature +21 -10
  20. data/features/verifying_doubles/README.md +17 -0
  21. data/features/verifying_doubles/class_doubles.feature +1 -16
  22. data/features/verifying_doubles/dynamic_classes.feature +0 -1
  23. data/features/verifying_doubles/{introduction.feature → instance_doubles.feature} +41 -23
  24. data/features/verifying_doubles/partial_doubles.feature +2 -2
  25. data/lib/rspec/mocks.rb +69 -82
  26. data/lib/rspec/mocks/any_instance/expect_chain_chain.rb +35 -0
  27. data/lib/rspec/mocks/any_instance/expectation_chain.rb +1 -2
  28. data/lib/rspec/mocks/any_instance/recorder.rb +52 -18
  29. data/lib/rspec/mocks/any_instance/stub_chain.rb +1 -1
  30. data/lib/rspec/mocks/any_instance/stub_chain_chain.rb +4 -0
  31. data/lib/rspec/mocks/argument_list_matcher.rb +10 -44
  32. data/lib/rspec/mocks/argument_matchers.rb +132 -163
  33. data/lib/rspec/mocks/configuration.rb +28 -4
  34. data/lib/rspec/mocks/error_generator.rb +46 -13
  35. data/lib/rspec/mocks/example_methods.rb +13 -12
  36. data/lib/rspec/mocks/extensions/marshal.rb +1 -1
  37. data/lib/rspec/mocks/framework.rb +3 -4
  38. data/lib/rspec/mocks/instance_method_stasher.rb +2 -3
  39. data/lib/rspec/mocks/matchers/have_received.rb +8 -6
  40. data/lib/rspec/mocks/matchers/receive.rb +28 -20
  41. data/lib/rspec/mocks/matchers/receive_message_chain.rb +65 -0
  42. data/lib/rspec/mocks/matchers/receive_messages.rb +3 -2
  43. data/lib/rspec/mocks/message_chain.rb +91 -0
  44. data/lib/rspec/mocks/message_expectation.rb +86 -80
  45. data/lib/rspec/mocks/method_double.rb +2 -11
  46. data/lib/rspec/mocks/method_reference.rb +82 -23
  47. data/lib/rspec/mocks/method_signature_verifier.rb +207 -0
  48. data/lib/rspec/mocks/mutate_const.rb +34 -50
  49. data/lib/rspec/mocks/object_reference.rb +0 -1
  50. data/lib/rspec/mocks/proxy.rb +70 -13
  51. data/lib/rspec/mocks/ruby_features.rb +24 -0
  52. data/lib/rspec/mocks/space.rb +105 -31
  53. data/lib/rspec/mocks/standalone.rb +2 -2
  54. data/lib/rspec/mocks/syntax.rb +43 -8
  55. data/lib/rspec/mocks/targets.rb +16 -7
  56. data/lib/rspec/mocks/test_double.rb +41 -15
  57. data/lib/rspec/mocks/verifying_double.rb +51 -4
  58. data/lib/rspec/mocks/verifying_message_expecation.rb +12 -12
  59. data/lib/rspec/mocks/verifying_proxy.rb +32 -19
  60. data/lib/rspec/mocks/version.rb +1 -1
  61. data/spec/rspec/mocks/and_call_original_spec.rb +28 -7
  62. data/spec/rspec/mocks/and_return_spec.rb +23 -0
  63. data/spec/rspec/mocks/and_yield_spec.rb +1 -2
  64. data/spec/rspec/mocks/any_instance_spec.rb +33 -17
  65. data/spec/rspec/mocks/array_including_matcher_spec.rb +6 -6
  66. data/spec/rspec/mocks/before_all_spec.rb +132 -0
  67. data/spec/rspec/mocks/block_return_value_spec.rb +12 -1
  68. data/spec/rspec/mocks/combining_implementation_instructions_spec.rb +9 -11
  69. data/spec/rspec/mocks/configuration_spec.rb +14 -1
  70. data/spec/rspec/mocks/double_spec.rb +867 -24
  71. data/spec/rspec/mocks/example_methods_spec.rb +13 -0
  72. data/spec/rspec/mocks/extensions/marshal_spec.rb +17 -17
  73. data/spec/rspec/mocks/failing_argument_matchers_spec.rb +29 -1
  74. data/spec/rspec/mocks/hash_excluding_matcher_spec.rb +12 -12
  75. data/spec/rspec/mocks/hash_including_matcher_spec.rb +21 -17
  76. data/spec/rspec/mocks/instance_method_stasher_spec.rb +2 -3
  77. data/spec/rspec/mocks/matchers/have_received_spec.rb +7 -0
  78. data/spec/rspec/mocks/matchers/receive_message_chain_spec.rb +198 -0
  79. data/spec/rspec/mocks/matchers/receive_messages_spec.rb +2 -2
  80. data/spec/rspec/mocks/matchers/receive_spec.rb +19 -6
  81. data/spec/rspec/mocks/method_signature_verifier_spec.rb +272 -0
  82. data/spec/rspec/mocks/methods_spec.rb +0 -1
  83. data/spec/rspec/mocks/multiple_return_value_spec.rb +2 -2
  84. data/spec/rspec/mocks/mutate_const_spec.rb +24 -1
  85. data/spec/rspec/mocks/nil_expectation_warning_spec.rb +6 -22
  86. data/spec/rspec/mocks/null_object_mock_spec.rb +13 -7
  87. data/spec/rspec/mocks/options_hash_spec.rb +3 -3
  88. data/spec/rspec/mocks/{partial_mock_spec.rb → partial_double_spec.rb} +5 -2
  89. data/spec/rspec/mocks/{partial_mock_using_mocks_directly_spec.rb → partial_double_using_mocks_directly_spec.rb} +1 -1
  90. data/spec/rspec/mocks/passing_argument_matchers_spec.rb +18 -0
  91. data/spec/rspec/mocks/serialization_spec.rb +1 -0
  92. data/spec/rspec/mocks/space_spec.rb +218 -7
  93. data/spec/rspec/mocks/stub_chain_spec.rb +6 -0
  94. data/spec/rspec/mocks/stub_spec.rb +0 -6
  95. data/spec/rspec/mocks/syntax_spec.rb +19 -0
  96. data/spec/rspec/mocks/test_double_spec.rb +0 -1
  97. data/spec/rspec/mocks/verifying_double_spec.rb +281 -18
  98. data/spec/rspec/mocks/verifying_message_expecation_spec.rb +7 -6
  99. data/spec/rspec/mocks_spec.rb +168 -42
  100. data/spec/spec_helper.rb +34 -22
  101. metadata +94 -63
  102. metadata.gz.sig +0 -0
  103. checksums.yaml +0 -15
  104. checksums.yaml.gz.sig +0 -2
  105. data/features/outside_rspec/configuration.feature +0 -60
  106. data/lib/rspec/mocks/arity_calculator.rb +0 -66
  107. data/lib/rspec/mocks/errors.rb +0 -12
  108. data/lib/rspec/mocks/mock.rb +0 -7
  109. data/lib/rspec/mocks/proxy_for_nil.rb +0 -37
  110. data/lib/rspec/mocks/stub_chain.rb +0 -51
  111. data/spec/rspec/mocks/argument_expectation_spec.rb +0 -32
  112. data/spec/rspec/mocks/arity_calculator_spec.rb +0 -95
  113. data/spec/rspec/mocks/mock_space_spec.rb +0 -113
  114. data/spec/rspec/mocks/mock_spec.rb +0 -788
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ module RSpec
4
+ module Mocks
5
+ describe ExampleMethods do
6
+ it 'does not define private helper methods since it gets included into a ' +
7
+ 'namespace where users define methods and could inadvertently overwrite ' +
8
+ 'them' do
9
+ expect(ExampleMethods.private_instance_methods).to eq([])
10
+ end
11
+ end
12
+ end
13
+ end
@@ -13,23 +13,6 @@ describe Marshal, 'extensions' do
13
13
  end
14
14
 
15
15
  describe '#dump' do
16
- context 'when rspec-mocks has not been fully initialized' do
17
- def without_space
18
- stashed_space, RSpec::Mocks.space = RSpec::Mocks.space, nil
19
- yield
20
- ensure
21
- RSpec::Mocks.space = stashed_space
22
- end
23
-
24
- it 'does not duplicate the object before serialization' do
25
- obj = UndupableObject.new
26
- without_space do
27
- serialized = Marshal.dump(obj)
28
- expect(Marshal.load(serialized)).to be_an(UndupableObject)
29
- end
30
- end
31
- end
32
-
33
16
  context 'when rspec-mocks has been fully initialized' do
34
17
  it 'duplicates objects with stubbed or mocked implementations before serialization' do
35
18
  obj = double(:foo => "bar")
@@ -50,5 +33,22 @@ describe Marshal, 'extensions' do
50
33
  expect(Marshal.load(serialized)).to be_nil
51
34
  end
52
35
  end
36
+
37
+ context 'outside the per-test lifecycle' do
38
+ def outside_per_test_lifecycle
39
+ RSpec::Mocks.teardown
40
+ yield
41
+ ensure
42
+ RSpec::Mocks.setup
43
+ end
44
+
45
+ it 'does not duplicate the object before serialization' do
46
+ obj = UndupableObject.new
47
+ outside_per_test_lifecycle do
48
+ serialized = Marshal.dump(obj)
49
+ expect(Marshal.load(serialized)).to be_an(UndupableObject)
50
+ end
51
+ end
52
+ end
53
53
  end
54
54
  end
@@ -63,9 +63,11 @@ module RSpec
63
63
  end
64
64
 
65
65
  it "matches against a Matcher" do
66
+ # This spec is generating warnings on 1.8.7, not sure why so
67
+ # this does with_isolated_stderr to kill them. @samphippen 3rd Jan 2013.
66
68
  expect do
67
69
  @double.should_receive(:msg).with(equal(3))
68
- @double.msg(37)
70
+ with_isolated_stderr { @double.msg(37) }
69
71
  end.to raise_error(RSpec::Mocks::MockExpectationError, "Double \"double\" received :msg with unexpected arguments\n expected: (equal 3)\n got: (37)")
70
72
  end
71
73
 
@@ -103,6 +105,17 @@ module RSpec
103
105
  end.to raise_error(ArgumentError, /must have at least one argument/)
104
106
  end
105
107
 
108
+ it "fails when given an arbitrary object that returns false from #===" do
109
+ matcher = double
110
+ matcher.should_receive(:===).with(4).at_least(:once).and_return(false)
111
+
112
+ @double.should_receive(:foo).with(matcher)
113
+
114
+ expect {
115
+ @double.foo(4)
116
+ }.to raise_error(RSpec::Mocks::MockExpectationError)
117
+ end
118
+
106
119
  it "fails with sensible message when args respond to #description" do
107
120
  arg = Class.new do
108
121
  def description
@@ -151,6 +164,21 @@ module RSpec
151
164
  @double.msg 3
152
165
  end.to raise_error(RSpec::Mocks::MockExpectationError, "Double \"double\" received :msg with unexpected arguments\n expected: (my_thing)\n got: (3)")
153
166
  end
167
+
168
+ it "fails a class against an unrelated class" do
169
+ @double.should_receive(:foo).with(Fixnum)
170
+ expect {
171
+ @double.foo(Hash)
172
+ }.to raise_error(RSpec::Mocks::MockExpectationError)
173
+ end
174
+
175
+ it "fails a class against an object of a different type" do
176
+ @double.should_receive(:foo).with(Fixnum)
177
+
178
+ expect {
179
+ @double.foo(3.2)
180
+ }.to raise_error(RSpec::Mocks::MockExpectationError)
181
+ end
154
182
  end
155
183
  end
156
184
  end
@@ -11,54 +11,54 @@ module RSpec
11
11
 
12
12
  describe "passing" do
13
13
  it "matches a hash without the specified key" do
14
- expect(hash_not_including(:c)).to eq({:a => 1, :b => 2})
14
+ expect(hash_not_including(:c)).to be === {:a => 1, :b => 2}
15
15
  end
16
16
 
17
17
  it "matches a hash with the specified key, but different value" do
18
- expect(hash_not_including(:b => 3)).to eq({:a => 1, :b => 2})
18
+ expect(hash_not_including(:b => 3)).to be === {:a => 1, :b => 2}
19
19
  end
20
20
 
21
21
  it "matches a hash without the specified key, given as anything()" do
22
- expect(hash_not_including(:c => anything)).to eq({:a => 1, :b => 2})
22
+ expect(hash_not_including(:c => anything)).to be === {:a => 1, :b => 2}
23
23
  end
24
24
 
25
25
  it "matches an empty hash" do
26
- expect(hash_not_including(:a)).to eq({})
26
+ expect(hash_not_including(:a)).to be === {}
27
27
  end
28
28
 
29
29
  it "matches a hash without any of the specified keys" do
30
- expect(hash_not_including(:a, :b, :c)).to eq(:d => 7)
30
+ expect(hash_not_including(:a, :b, :c)).to be === { :d => 7 }
31
31
  end
32
32
 
33
33
  end
34
34
 
35
35
  describe "failing" do
36
36
  it "does not match a non-hash" do
37
- expect(hash_not_including(:a => 1)).not_to eq 1
37
+ expect(hash_not_including(:a => 1)).not_to be === 1
38
38
  end
39
39
 
40
40
  it "does not match a hash with a specified key" do
41
- expect(hash_not_including(:b)).not_to eq(:b => 2)
41
+ expect(hash_not_including(:b)).not_to be === { :b => 2 }
42
42
  end
43
43
 
44
44
  it "does not match a hash with the specified key/value pair" do
45
- expect(hash_not_including(:b => 2)).not_to eq(:a => 1, :b => 2)
45
+ expect(hash_not_including(:b => 2)).not_to be === { :a => 1, :b => 2 }
46
46
  end
47
47
 
48
48
  it "does not match a hash with the specified key" do
49
- expect(hash_not_including(:a, :b => 3)).not_to eq(:a => 1, :b => 2)
49
+ expect(hash_not_including(:a, :b => 3)).not_to be === { :a => 1, :b => 2 }
50
50
  end
51
51
 
52
52
  it "does not match a hash with one of the specified keys" do
53
- expect(hash_not_including(:a, :b)).not_to eq(:b => 2)
53
+ expect(hash_not_including(:a, :b)).not_to be === { :b => 2 }
54
54
  end
55
55
 
56
56
  it "does not match a hash with some of the specified keys" do
57
- expect(hash_not_including(:a, :b, :c)).not_to eq(:a => 1, :b => 2)
57
+ expect(hash_not_including(:a, :b, :c)).not_to be === { :a => 1, :b => 2 }
58
58
  end
59
59
 
60
60
  it "does not match a hash with one key/value pair included" do
61
- expect(hash_not_including(:a, :b, :c, :d => 7)).not_to eq(:d => 7)
61
+ expect(hash_not_including(:a, :b, :c, :d => 7)).not_to be === { :d => 7 }
62
62
  end
63
63
  end
64
64
  end
@@ -11,77 +11,81 @@ module RSpec
11
11
 
12
12
  describe "passing" do
13
13
  it "matches the same hash" do
14
- expect(hash_including(:a => 1)).to eq({:a => 1})
14
+ expect(hash_including(:a => 1)).to be === {:a => 1}
15
15
  end
16
16
 
17
17
  it "matches a hash with extra stuff" do
18
- expect(hash_including(:a => 1)).to eq({:a => 1, :b => 2})
18
+ expect(hash_including(:a => 1)).to be === {:a => 1, :b => 2}
19
19
  end
20
20
 
21
21
  describe "when matching against other matchers" do
22
22
  it "matches an int against anything()" do
23
- expect(hash_including(:a => anything, :b => 2)).to eq({:a => 1, :b => 2})
23
+ expect(hash_including(:a => anything, :b => 2)).to be === {:a => 1, :b => 2}
24
24
  end
25
25
 
26
26
  it "matches a string against anything()" do
27
- expect(hash_including(:a => anything, :b => 2)).to eq({:a => "1", :b => 2})
27
+ expect(hash_including(:a => anything, :b => 2)).to be === {:a => "1", :b => 2}
28
+ end
29
+
30
+ it 'can match against arbitrary objects that implement #===' do
31
+ expect(hash_including(:a => /foo/)).to be === { :a => "foobar" }
28
32
  end
29
33
  end
30
34
 
31
35
  describe "when passed only keys or keys mixed with key/value pairs" do
32
36
  it "matches if the key is present" do
33
- expect(hash_including(:a)).to eq({:a => 1, :b => 2})
37
+ expect(hash_including(:a)).to be === {:a => 1, :b => 2}
34
38
  end
35
39
 
36
40
  it "matches if more keys are present" do
37
- expect(hash_including(:a, :b)).to eq({:a => 1, :b => 2, :c => 3})
41
+ expect(hash_including(:a, :b)).to be === {:a => 1, :b => 2, :c => 3}
38
42
  end
39
43
 
40
44
  it "matches a string against a given key" do
41
- expect(hash_including(:a)).to eq({:a => "1", :b => 2})
45
+ expect(hash_including(:a)).to be === {:a => "1", :b => 2}
42
46
  end
43
47
 
44
48
  it "matches if passed one key and one key/value pair" do
45
- expect(hash_including(:a, :b => 2)).to eq({:a => 1, :b => 2})
49
+ expect(hash_including(:a, :b => 2)).to be === {:a => 1, :b => 2}
46
50
  end
47
51
 
48
52
  it "matches if passed many keys and one key/value pair" do
49
- expect(hash_including(:a, :b, :c => 3)).to eq({:a => 1, :b => 2, :c => 3, :d => 4})
53
+ expect(hash_including(:a, :b, :c => 3)).to be === {:a => 1, :b => 2, :c => 3, :d => 4}
50
54
  end
51
55
 
52
56
  it "matches if passed many keys and many key/value pairs" do
53
- expect(hash_including(:a, :b, :c => 3, :e => 5)).to eq({:a => 1, :b => 2, :c => 3, :d => 4, :e => 5})
57
+ expect(hash_including(:a, :b, :c => 3, :e => 5)).to be === {:a => 1, :b => 2, :c => 3, :d => 4, :e => 5}
54
58
  end
55
59
  end
56
60
  end
57
61
 
58
62
  describe "failing" do
59
63
  it "does not match a non-hash" do
60
- expect(hash_including(:a => 1)).not_to eq 1
64
+ expect(hash_including(:a => 1)).not_to be === 1
61
65
  end
62
66
 
63
67
  it "does not match a hash with a missing key" do
64
- expect(hash_including(:a => 1)).not_to eq(:b => 2)
68
+ expect(hash_including(:a => 1)).not_to be === { :b => 2 }
65
69
  end
66
70
 
67
71
  it "does not match a hash with a missing key" do
68
- expect(hash_including(:a)).not_to eq(:b => 2)
72
+ expect(hash_including(:a)).not_to be === { :b => 2 }
69
73
  end
70
74
 
71
75
  it "does not match an empty hash with a given key" do
72
- expect(hash_including(:a)).not_to eq({})
76
+ expect(hash_including(:a)).not_to be === {}
73
77
  end
74
78
 
75
79
  it "does not match a hash with a missing key when one pair is matching" do
76
- expect(hash_including(:a, :b => 2)).not_to eq(:b => 2)
80
+ expect(hash_including(:a, :b => 2)).not_to be === { :b => 2 }
77
81
  end
78
82
 
79
83
  it "does not match a hash with an incorrect value" do
80
- expect(hash_including(:a => 1, :b => 2)).not_to eq(:a => 1, :b => 3)
84
+ expect(hash_including(:a => 1, :b => 2)).not_to be === { :a => 1, :b => 3 }
81
85
  end
82
86
 
83
87
  it "does not match when values are nil but keys are different" do
84
- expect(hash_including(:a => nil)).not_to eq(:b => nil)
88
+ expect(hash_including(:a => nil)).not_to be === { :b => nil }
85
89
  end
86
90
  end
87
91
  end
@@ -24,7 +24,7 @@ module RSpec
24
24
  stashed_method = stasher_for(obj, :hello)
25
25
  stashed_method.stash
26
26
 
27
- def obj.hello; :overridden_hello; end
27
+ with_isolated_stderr { def obj.hello; :overridden_hello; end }
28
28
  expect(obj.hello).to eql :overridden_hello
29
29
 
30
30
  stashed_method.restore
@@ -39,7 +39,7 @@ module RSpec
39
39
  stashed_method = stasher_for(obj, :hello)
40
40
  stashed_method.stash
41
41
 
42
- def obj.hello; :overridden_hello; end
42
+ with_isolated_stderr { def obj.hello; :overridden_hello; end }
43
43
  stashed_method.restore
44
44
  expect(obj.send(:hello)).to eql :hello_defined_on_singleton_class
45
45
  end
@@ -72,4 +72,3 @@ module RSpec
72
72
  end
73
73
  end
74
74
  end
75
-
@@ -132,6 +132,13 @@ module RSpec
132
132
  expect(matcher.description).to eq 'have received expected_method(:expected_args) 1 time'
133
133
  end
134
134
 
135
+ it 'can generate a description after mocks have been torn down (e.g. when rspec-core requests it)' do
136
+ matcher = have_received(:expected_method).with(:expected_args).once
137
+ matcher.matches?(double(:expected_method => 1))
138
+ RSpec::Mocks.teardown
139
+ expect(matcher.description).to eq 'have received expected_method(:expected_args) 1 time'
140
+ end
141
+
135
142
  context "counts" do
136
143
  let(:dbl) { double(:expected_method => nil) }
137
144
 
@@ -0,0 +1,198 @@
1
+ require "spec_helper"
2
+
3
+
4
+ module RSpec::Mocks::Matchers
5
+ describe "receive_message_chain" do
6
+ let(:object) { double(:object) }
7
+
8
+ context "with only the expect syntax enabled" do
9
+ include_context "with syntax", :expect
10
+
11
+ it "errors with a negative allowance" do
12
+ expect {
13
+ allow(object).not_to receive_message_chain(:to_a)
14
+ }.to raise_error(RSpec::Mocks::NegationUnsupportedError)
15
+ end
16
+
17
+ it "errors with a negative expectation" do
18
+ expect {
19
+ expect(object).not_to receive_message_chain(:to_a)
20
+ }.to raise_error(RSpec::Mocks::NegationUnsupportedError)
21
+ end
22
+
23
+ it "errors with a negative any_instance expectation" do
24
+ expect {
25
+ expect_any_instance_of(Object).not_to receive_message_chain(:to_a)
26
+ }.to raise_error(RSpec::Mocks::NegationUnsupportedError)
27
+ end
28
+
29
+ it "errors with a negative any_instance allowance" do
30
+ expect {
31
+ allow_any_instance_of(Object).not_to receive_message_chain(:to_a)
32
+ }.to raise_error(RSpec::Mocks::NegationUnsupportedError)
33
+ end
34
+
35
+ it "works with a do block" do
36
+ allow(object).to receive_message_chain(:to_a, :length) do
37
+ 3
38
+ end
39
+
40
+ expect(object.to_a.length).to eq(3)
41
+ end
42
+
43
+ it "works with a {} block" do
44
+ allow(object).to receive_message_chain(:to_a, :length) { 3 }
45
+
46
+ expect(object.to_a.length).to eq(3)
47
+ end
48
+
49
+ it "gives the { } block prescedence over the do block" do
50
+ allow(object).to receive_message_chain(:to_a, :length) { 3 } do
51
+ 4
52
+ end
53
+
54
+ expect(object.to_a.length).to eq(3)
55
+ end
56
+
57
+ it "works with and_return" do
58
+ allow(object).to receive_message_chain(:to_a, :length).and_return(3)
59
+
60
+ expect(object.to_a.length).to eq(3)
61
+ end
62
+
63
+ it "works with and_call_original", :pending => "See https://github.com/rspec/rspec-mocks/pull/467#issuecomment-28631621" do
64
+ list = [1, 2, 3]
65
+ expect(list).to receive_message_chain(:to_a, :length).and_call_original
66
+ expect(list.to_a.length).to eq(3)
67
+ end
68
+
69
+ it "fails with and_call_original when the entire chain is not called", :pending => "See https://github.com/rspec/rspec-mocks/pull/467#issuecomment-28631621" do
70
+ list = [1, 2, 3]
71
+ expect(list).to receive_message_chain(:to_a, :length).and_call_original
72
+ expect(list.to_a).to eq([1, 2, 3])
73
+ end
74
+
75
+ it "works with and_raise" do
76
+ allow(object).to receive_message_chain(:to_a, :length).and_raise(StandardError.new("hi"))
77
+
78
+ expect { object.to_a.length }.to raise_error(StandardError, "hi")
79
+ end
80
+
81
+ it "works with and_throw" do
82
+ allow(object).to receive_message_chain(:to_a, :length).and_throw(:nope)
83
+
84
+ expect { object.to_a.length }.to throw_symbol(:nope)
85
+ end
86
+
87
+ it "works with and_yield" do
88
+ allow(object).to receive_message_chain(:to_a, :length).and_yield(3)
89
+
90
+ expect { |blk| object.to_a.length(&blk) }.to yield_with_args(3)
91
+ end
92
+
93
+ it "works with a string of messages to chain" do
94
+ allow(object).to receive_message_chain("to_a.length").and_yield(3)
95
+
96
+ expect { |blk| object.to_a.length(&blk) }.to yield_with_args(3)
97
+ end
98
+
99
+ it "works with a hash return as the last argument in the chain" do
100
+ allow(object).to receive_message_chain(:to_a, :length => 3)
101
+
102
+ expect(object.to_a.length).to eq(3)
103
+ end
104
+
105
+ it "accepts any number of arguments to the stubbed messages" do
106
+ allow(object).to receive_message_chain(:msg1, :msg2).and_return(:return_value)
107
+
108
+ expect(object.msg1("nonsense", :value).msg2("another", :nonsense, 3.0, "value")).to eq(:return_value)
109
+ end
110
+
111
+ it "accepts any number of arguments to the stubbed messages with an inline hash return value" do
112
+ allow(object).to receive_message_chain(:msg1, :msg2 => :return_value)
113
+
114
+ expect(object.msg1("nonsense", :value).msg2("another", :nonsense, 3.0, "value")).to eq(:return_value)
115
+ end
116
+
117
+ it "raises when expect is used and the entire chain isn't called" do
118
+ expect {
119
+ expect(object).to receive_message_chain(:to_a, :farce, :length => 3)
120
+ object.to_a
121
+ verify_all
122
+ }.to raise_error(RSpec::Mocks::MockExpectationError)
123
+ end
124
+
125
+ it "does not raise when expect is used and the entire chain is called" do
126
+ expect {
127
+ expect(object).to receive_message_chain(:to_a, :length => 3)
128
+ object.to_a.length
129
+ verify_all
130
+ }.not_to raise_error
131
+ end
132
+
133
+ it "works with allow_any_instance" do
134
+ o = Object.new
135
+
136
+ allow_any_instance_of(Object).to receive_message_chain(:to_a, :length => 3)
137
+
138
+ expect(o.to_a.length).to eq(3)
139
+ end
140
+
141
+ it "fails when with expect_any_instance_of is used and the entire chain is not called" do
142
+ expect {
143
+ expect_any_instance_of(Object).to receive_message_chain(:to_a, :length => 3)
144
+ verify_all
145
+ }.to raise_error(RSpec::Mocks::MockExpectationError)
146
+ end
147
+
148
+ it "passes when with expect_any_instance_of is used and the entire chain is called" do
149
+ o = Object.new
150
+
151
+ expect_any_instance_of(Object).to receive_message_chain(:to_a, :length => 3)
152
+ o.to_a.length
153
+ end
154
+
155
+ it "works with expect where the first level of the chain is already expected" do
156
+ o = Object.new
157
+ expect(o).to receive(:foo).and_return(double)
158
+ expect(o).to receive_message_chain(:foo, :bar, :baz)
159
+
160
+ o.foo.bar.baz
161
+ end
162
+
163
+ it "works with allow where the first level of the chain is already expected" do
164
+ o = Object.new
165
+ expect(o).to receive(:foo).and_return(double)
166
+ allow(o).to receive_message_chain(:foo, :bar, :baz).and_return(3)
167
+
168
+ expect(o.foo.bar.baz).to eq(3)
169
+ end
170
+
171
+ it "works with expect where the first level of the chain is already stubbed" do
172
+ o = Object.new
173
+ allow(o).to receive(:foo).and_return(double)
174
+ expect(o).to receive_message_chain(:foo, :bar, :baz)
175
+
176
+ o.foo.bar.baz
177
+ end
178
+
179
+ it "works with allow where the first level of the chain is already stubbed" do
180
+ o = Object.new
181
+ allow(o).to receive(:foo).and_return(double)
182
+ allow(o).to receive_message_chain(:foo, :bar, :baz).and_return(3)
183
+
184
+ expect(o.foo.bar.baz).to eq(3)
185
+ end
186
+ end
187
+
188
+ context "when the expect and should syntaxes are enabled" do
189
+ include_context "with syntax", [:expect, :should]
190
+
191
+ it "stubs the message correctly" do
192
+ allow(object).to receive_message_chain(:to_a, :length)
193
+
194
+ expect { object.to_a.length }.not_to raise_error
195
+ end
196
+ end
197
+ end
198
+ end