rspec-mocks 2.13.1 → 2.14.0.rc1
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.
- data/Changelog.md +45 -4
- data/README.md +1 -1
- data/features/argument_matchers/README.md +2 -2
- data/features/argument_matchers/explicit.feature +2 -3
- data/features/argument_matchers/general_matchers.feature +2 -2
- data/features/argument_matchers/type_matchers.feature +3 -4
- data/features/message_expectations/README.md +2 -2
- data/features/message_expectations/any_instance.feature +2 -2
- data/features/message_expectations/block_local_expectations.feature.pending +3 -3
- data/features/message_expectations/expect_message_using_expect.feature +103 -0
- data/features/message_expectations/expect_message_using_should_receive.feature +118 -0
- data/features/message_expectations/receive_counts.feature +1 -1
- data/features/method_stubs/README.md +1 -1
- data/features/method_stubs/any_instance.feature +11 -11
- data/features/method_stubs/as_null_object.feature +1 -1
- data/features/method_stubs/stub_implementation.feature +2 -2
- data/features/outside_rspec/configuration.feature +0 -20
- data/features/spies/spy_partial_mock_method.feature +34 -0
- data/features/spies/spy_pure_mock_method.feature +76 -0
- data/features/spies/spy_unstubbed_method.feature +18 -0
- data/features/step_definitions/additional_cli_steps.rb +7 -0
- data/features/test_frameworks/test_unit.feature +43 -0
- data/lib/rspec/mocks.rb +9 -34
- data/lib/rspec/mocks/any_instance/chain.rb +8 -2
- data/lib/rspec/mocks/any_instance/expectation_chain.rb +19 -16
- data/lib/rspec/mocks/any_instance/recorder.rb +6 -3
- data/lib/rspec/mocks/any_instance/stub_chain.rb +11 -11
- data/lib/rspec/mocks/any_instance/stub_chain_chain.rb +8 -10
- data/lib/rspec/mocks/argument_list_matcher.rb +7 -3
- data/lib/rspec/mocks/configuration.rb +28 -1
- data/lib/rspec/mocks/deprecation.rb +18 -0
- data/lib/rspec/mocks/error_generator.rb +60 -8
- data/lib/rspec/mocks/errors.rb +1 -1
- data/lib/rspec/mocks/example_methods.rb +39 -3
- data/lib/rspec/mocks/extensions/marshal.rb +4 -10
- data/lib/rspec/mocks/framework.rb +16 -4
- data/lib/rspec/mocks/instance_method_stasher.rb +3 -0
- data/lib/rspec/mocks/matchers/have_received.rb +93 -0
- data/lib/rspec/mocks/matchers/receive.rb +92 -0
- data/lib/rspec/mocks/message_expectation.rb +66 -129
- data/lib/rspec/mocks/method_double.rb +50 -43
- data/lib/rspec/mocks/mutate_const.rb +8 -20
- data/lib/rspec/mocks/proxy.rb +41 -25
- data/lib/rspec/mocks/proxy_for_nil.rb +36 -0
- data/lib/rspec/mocks/space.rb +64 -11
- data/lib/rspec/mocks/stub_chain.rb +51 -0
- data/lib/rspec/mocks/syntax.rb +329 -0
- data/lib/rspec/mocks/targets.rb +69 -0
- data/lib/rspec/mocks/test_double.rb +25 -4
- data/lib/rspec/mocks/version.rb +1 -1
- data/lib/spec/mocks.rb +1 -3
- data/spec/rspec/mocks/and_call_original_spec.rb +8 -0
- data/spec/rspec/mocks/and_yield_spec.rb +6 -6
- data/spec/rspec/mocks/any_instance_spec.rb +43 -31
- data/spec/rspec/mocks/any_number_of_times_spec.rb +6 -0
- data/spec/rspec/mocks/argument_expectation_spec.rb +12 -14
- data/spec/rspec/mocks/at_least_spec.rb +46 -37
- data/spec/rspec/mocks/at_most_spec.rb +12 -12
- data/spec/rspec/mocks/block_return_value_spec.rb +18 -1
- data/spec/rspec/mocks/bug_report_10260_spec.rb +1 -1
- data/spec/rspec/mocks/bug_report_10263_spec.rb +1 -1
- data/spec/rspec/mocks/bug_report_11545_spec.rb +4 -4
- data/spec/rspec/mocks/bug_report_600_spec.rb +1 -1
- data/spec/rspec/mocks/bug_report_7611_spec.rb +1 -1
- data/spec/rspec/mocks/configuration_spec.rb +124 -0
- data/spec/rspec/mocks/double_spec.rb +13 -1
- data/spec/rspec/mocks/failing_argument_matchers_spec.rb +17 -1
- data/spec/rspec/mocks/hash_excluding_matcher_spec.rb +13 -13
- data/spec/rspec/mocks/matchers/have_received_spec.rb +266 -0
- data/spec/rspec/mocks/matchers/receive_spec.rb +318 -0
- data/spec/rspec/mocks/methods_spec.rb +27 -0
- data/spec/rspec/mocks/mock_ordering_spec.rb +4 -4
- data/spec/rspec/mocks/mock_space_spec.rb +94 -39
- data/spec/rspec/mocks/mock_spec.rb +65 -50
- data/spec/rspec/mocks/multiple_return_value_spec.rb +10 -10
- data/spec/rspec/mocks/mutate_const_spec.rb +21 -1
- data/spec/rspec/mocks/nil_expectation_warning_spec.rb +10 -4
- data/spec/rspec/mocks/null_object_mock_spec.rb +11 -2
- data/spec/rspec/mocks/once_counts_spec.rb +5 -5
- data/spec/rspec/mocks/options_hash_spec.rb +4 -4
- data/spec/rspec/mocks/partial_mock_spec.rb +20 -11
- data/spec/rspec/mocks/partial_mock_using_mocks_directly_spec.rb +7 -7
- data/spec/rspec/mocks/passing_argument_matchers_spec.rb +2 -2
- data/spec/rspec/mocks/precise_counts_spec.rb +6 -6
- data/spec/rspec/mocks/serialization_spec.rb +1 -22
- data/spec/rspec/mocks/stash_spec.rb +4 -12
- data/spec/rspec/mocks/stub_implementation_spec.rb +3 -3
- data/spec/rspec/mocks/stub_spec.rb +44 -20
- data/spec/rspec/mocks/stubbed_message_expectations_spec.rb +6 -6
- data/spec/rspec/mocks/twice_counts_spec.rb +6 -6
- data/spec/rspec/mocks_spec.rb +1 -3
- data/spec/spec_helper.rb +25 -1
- metadata +86 -81
- data/features/message_expectations/expect_message.feature +0 -94
- data/lib/rspec/mocks/any_instance.rb +0 -81
- data/lib/rspec/mocks/extensions/psych.rb +0 -23
- data/lib/rspec/mocks/methods.rb +0 -155
- data/lib/rspec/mocks/serialization.rb +0 -34
- data/spec/rspec/mocks/combining_implementation_instructions_spec.rb +0 -197
@@ -4,9 +4,21 @@ describe "double" do
|
|
4
4
|
it "is an alias for stub and mock" do
|
5
5
|
expect(double()).to be_a(RSpec::Mocks::Mock)
|
6
6
|
end
|
7
|
-
|
7
|
+
|
8
8
|
it "uses 'Double' in failure messages" do
|
9
9
|
double = double('name')
|
10
10
|
expect {double.foo}.to raise_error(/Double "name" received/)
|
11
11
|
end
|
12
|
+
|
13
|
+
describe "deprecated aliases" do
|
14
|
+
it "warns if #stub is used" do
|
15
|
+
expect(RSpec).to receive(:deprecate).with("stub", :replacement => "double")
|
16
|
+
stub("TestDouble")
|
17
|
+
end
|
18
|
+
|
19
|
+
it "warns if #mock is used" do
|
20
|
+
expect(RSpec).to receive(:deprecate).with("mock", :replacement => "double")
|
21
|
+
mock("TestDouble")
|
22
|
+
end
|
23
|
+
end
|
12
24
|
end
|
@@ -9,7 +9,7 @@ module RSpec
|
|
9
9
|
end
|
10
10
|
|
11
11
|
after(:each) do
|
12
|
-
@double
|
12
|
+
reset @double
|
13
13
|
end
|
14
14
|
|
15
15
|
it "rejects non boolean" do
|
@@ -89,6 +89,22 @@ module RSpec
|
|
89
89
|
@double.msg :no_msg_for_you
|
90
90
|
end.to raise_error(RSpec::Expectations::ExpectationNotMetError, /expected: :received.*\s*.*got: :no_msg_for_you/)
|
91
91
|
end
|
92
|
+
|
93
|
+
it "fails with sensible message when args respond to #description" do
|
94
|
+
arg = Class.new do
|
95
|
+
def description
|
96
|
+
end
|
97
|
+
|
98
|
+
def inspect
|
99
|
+
"my_thing"
|
100
|
+
end
|
101
|
+
end.new
|
102
|
+
|
103
|
+
expect do
|
104
|
+
@double.should_receive(:msg).with(3)
|
105
|
+
@double.msg arg
|
106
|
+
end.to raise_error(RSpec::Mocks::MockExpectationError, "Double \"double\" received :msg with unexpected arguments\n expected: (3)\n got: (my_thing)")
|
107
|
+
end
|
92
108
|
end
|
93
109
|
end
|
94
110
|
end
|
@@ -4,20 +4,20 @@ module RSpec
|
|
4
4
|
module Mocks
|
5
5
|
module ArgumentMatchers
|
6
6
|
describe HashExcludingMatcher do
|
7
|
-
|
7
|
+
|
8
8
|
it "describes itself properly" do
|
9
9
|
expect(HashExcludingMatcher.new(:a => 5).description).to eq "hash_not_including(:a=>5)"
|
10
|
-
end
|
10
|
+
end
|
11
11
|
|
12
12
|
describe "passing" do
|
13
13
|
it "matches a hash without the specified key" do
|
14
14
|
expect(hash_not_including(:c)).to eq({:a => 1, :b => 2})
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
it "matches a hash with the specified key, but different value" do
|
18
18
|
expect(hash_not_including(:b => 3)).to eq({:a => 1, :b => 2})
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
it "matches a hash without the specified key, given as anything()" do
|
22
22
|
expect(hash_not_including(:c => anything)).to eq({:a => 1, :b => 2})
|
23
23
|
end
|
@@ -25,38 +25,38 @@ module RSpec
|
|
25
25
|
it "matches an empty hash" do
|
26
26
|
expect(hash_not_including(:a)).to eq({})
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
it "matches a hash without any of the specified keys" do
|
30
30
|
expect(hash_not_including(:a, :b, :c)).to eq(: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
37
|
expect(hash_not_including(:a => 1)).not_to eq 1
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
it "does not match a hash with a specified key" do
|
41
41
|
expect(hash_not_including(:b)).not_to eq(:b => 2)
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
it "does not match a hash with the specified key/value pair" do
|
45
45
|
expect(hash_not_including(:b => 2)).not_to eq(:a => 1, :b => 2)
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
it "does not match a hash with the specified key" do
|
49
49
|
expect(hash_not_including(:a, :b => 3)).not_to eq(: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
53
|
expect(hash_not_including(:a, :b)).not_to eq(:b => 2)
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
it "does not match a hash with some of the specified keys" do
|
57
57
|
expect(hash_not_including(:a, :b, :c)).not_to eq(: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
61
|
expect(hash_not_including(:a, :b, :c, :d => 7)).not_to eq(:d => 7)
|
62
62
|
end
|
@@ -0,0 +1,266 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module Mocks
|
5
|
+
describe Matchers::HaveReceived do
|
6
|
+
describe "expect(...).to have_received" do
|
7
|
+
it 'passes when the double has received the given message' do
|
8
|
+
dbl = double_with_met_expectation(:expected_method)
|
9
|
+
expect(dbl).to have_received(:expected_method)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'passes when a null object has received the given message' do
|
13
|
+
dbl = null_object_with_met_expectation(:expected_method)
|
14
|
+
expect(dbl).to have_received(:expected_method)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'fails when the double has not received the given message' do
|
18
|
+
dbl = double_with_unmet_expectation(:expected_method)
|
19
|
+
|
20
|
+
expect {
|
21
|
+
expect(dbl).to have_received(:expected_method)
|
22
|
+
}.to raise_error(/expected: 1 time/)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'fails when a null object has not received the given message' do
|
26
|
+
dbl = double.as_null_object
|
27
|
+
|
28
|
+
expect {
|
29
|
+
expect(dbl).to have_received(:expected_method)
|
30
|
+
}.to raise_error(/expected: 1 time/)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'fails when the method has not been previously stubbed' do
|
34
|
+
dbl = double
|
35
|
+
|
36
|
+
expect {
|
37
|
+
expect(dbl).to have_received(:expected_method)
|
38
|
+
}.to raise_error(/method has not been stubbed/)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'fails when the method has been mocked' do
|
42
|
+
dbl = double
|
43
|
+
dbl.should_receive(:expected_method)
|
44
|
+
dbl.expected_method
|
45
|
+
|
46
|
+
expect {
|
47
|
+
expect(dbl).to have_received(:expected_method)
|
48
|
+
}.to raise_error(/method has been mocked instead of stubbed/)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'resets expectations on class methods when mocks are reset' do
|
52
|
+
dbl = Object
|
53
|
+
dbl.stub(:expected_method)
|
54
|
+
dbl.expected_method
|
55
|
+
reset dbl
|
56
|
+
dbl.stub(:expected_method)
|
57
|
+
|
58
|
+
expect {
|
59
|
+
expect(dbl).to have_received(:expected_method)
|
60
|
+
}.to raise_error(/0 times/)
|
61
|
+
end
|
62
|
+
|
63
|
+
context "with" do
|
64
|
+
it 'passes when the given args match the args used with the message' do
|
65
|
+
dbl = double_with_met_expectation(:expected_method, :expected, :args)
|
66
|
+
expect(dbl).to have_received(:expected_method).with(:expected, :args)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'fails when the given args do not match the args used with the message' do
|
70
|
+
dbl = double_with_met_expectation(:expected_method, :expected, :args)
|
71
|
+
|
72
|
+
expect {
|
73
|
+
expect(dbl).to have_received(:expected_method).with(:unexpected, :args)
|
74
|
+
}.to raise_error(/with unexpected arguments/)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'generates a useful description' do
|
79
|
+
matcher = have_received(:expected_method).with(:expected_args).once
|
80
|
+
expect(matcher.description).to eq 'have received expected_method(:expected_args) 1 time'
|
81
|
+
end
|
82
|
+
|
83
|
+
context "counts" do
|
84
|
+
let(:dbl) { double(:expected_method => nil) }
|
85
|
+
|
86
|
+
before do
|
87
|
+
dbl.expected_method
|
88
|
+
dbl.expected_method
|
89
|
+
dbl.expected_method
|
90
|
+
end
|
91
|
+
|
92
|
+
context "exactly" do
|
93
|
+
it 'passes when the message was received the given number of times' do
|
94
|
+
expect(dbl).to have_received(:expected_method).exactly(3).times
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'fails when the message was received more times' do
|
98
|
+
expect {
|
99
|
+
expect(dbl).to have_received(:expected_method).exactly(2).times
|
100
|
+
}.to raise_error(/expected: 2 times.*received: 3 times/m)
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'fails when the message was received fewer times' do
|
104
|
+
expect {
|
105
|
+
expect(dbl).to have_received(:expected_method).exactly(4).times
|
106
|
+
}.to raise_error(/expected: 4 times.*received: 3 times/m)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'at_least' do
|
111
|
+
it 'passes when the message was received the given number of times' do
|
112
|
+
expect(dbl).to have_received(:expected_method).at_least(3).times
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'passes when the message was received more times' do
|
116
|
+
expect(dbl).to have_received(:expected_method).at_least(2).times
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'fails when the message was received fewer times' do
|
120
|
+
expect {
|
121
|
+
expect(dbl).to have_received(:expected_method).at_least(4).times
|
122
|
+
}.to raise_error(/expected: at least 4 times.*received: 3 times/m)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
context 'at_most' do
|
127
|
+
it 'passes when the message was received the given number of times' do
|
128
|
+
expect(dbl).to have_received(:expected_method).at_most(3).times
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'passes when the message was received fewer times' do
|
132
|
+
expect(dbl).to have_received(:expected_method).at_most(4).times
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'fails when the message was received more times' do
|
136
|
+
expect {
|
137
|
+
expect(dbl).to have_received(:expected_method).at_most(2).times
|
138
|
+
}.to raise_error(/expected: at most 2 times.*received: 3 times/m)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
context 'once' do
|
143
|
+
it 'passes when the message was received once' do
|
144
|
+
dbl = double(:expected_method => nil)
|
145
|
+
dbl.expected_method
|
146
|
+
expect(dbl).to have_received(:expected_method).once
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'fails when the message was never received' do
|
150
|
+
dbl = double(:expected_method => nil)
|
151
|
+
|
152
|
+
expect {
|
153
|
+
expect(dbl).to have_received(:expected_method).once
|
154
|
+
}.to raise_error(/expected: 1 time.*received: 0 times/m)
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'fails when the message was received twice' do
|
158
|
+
dbl = double(:expected_method => nil)
|
159
|
+
dbl.expected_method
|
160
|
+
dbl.expected_method
|
161
|
+
|
162
|
+
expect {
|
163
|
+
expect(dbl).to have_received(:expected_method).once
|
164
|
+
}.to raise_error(/expected: 1 time.*received: 2 times/m)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
context 'twice' do
|
169
|
+
it 'passes when the message was received twice' do
|
170
|
+
dbl = double(:expected_method => nil)
|
171
|
+
dbl.expected_method
|
172
|
+
dbl.expected_method
|
173
|
+
|
174
|
+
expect(dbl).to have_received(:expected_method).twice
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'fails when the message was received once' do
|
178
|
+
dbl = double(:expected_method => nil)
|
179
|
+
dbl.expected_method
|
180
|
+
|
181
|
+
expect {
|
182
|
+
expect(dbl).to have_received(:expected_method).twice
|
183
|
+
}.to raise_error(/expected: 2 times.*received: 1 time/m)
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'fails when the message was received thrice' do
|
187
|
+
dbl = double(:expected_method => nil)
|
188
|
+
dbl.expected_method
|
189
|
+
dbl.expected_method
|
190
|
+
dbl.expected_method
|
191
|
+
|
192
|
+
expect {
|
193
|
+
expect(dbl).to have_received(:expected_method).twice
|
194
|
+
}.to raise_error(/expected: 2 times.*received: 3 times/m)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
describe "expect(...).not_to have_received" do
|
201
|
+
it 'passes when the double has not received the given message' do
|
202
|
+
dbl = double_with_unmet_expectation(:expected_method)
|
203
|
+
expect(dbl).not_to have_received(:expected_method)
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'fails when the double has received the given message' do
|
207
|
+
dbl = double_with_met_expectation(:expected_method)
|
208
|
+
|
209
|
+
expect {
|
210
|
+
expect(dbl).not_to have_received(:expected_method)
|
211
|
+
}.to raise_error(/expected: 0 times.*received: 1 time/m)
|
212
|
+
end
|
213
|
+
|
214
|
+
it 'fails when the method has not been previously stubbed' do
|
215
|
+
dbl = double
|
216
|
+
|
217
|
+
expect {
|
218
|
+
expect(dbl).not_to have_received(:expected_method)
|
219
|
+
}.to raise_error(/method has not been stubbed/)
|
220
|
+
end
|
221
|
+
|
222
|
+
context "with" do
|
223
|
+
it 'passes when the given args do not match the args used with the message' do
|
224
|
+
dbl = double_with_met_expectation(:expected_method, :expected, :args)
|
225
|
+
expect(dbl).not_to have_received(:expected_method).with(:unexpected, :args)
|
226
|
+
end
|
227
|
+
|
228
|
+
it 'fails when the given args match the args used with the message' do
|
229
|
+
dbl = double_with_met_expectation(:expected_method, :expected, :args)
|
230
|
+
|
231
|
+
expect {
|
232
|
+
expect(dbl).not_to have_received(:expected_method).with(:expected, :args)
|
233
|
+
}.to raise_error(/expected: 0 times.*received: 1 time/m) # TODO: better message
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
%w(exactly at_least at_most times once twice).each do |constraint|
|
238
|
+
it "does not allow #{constraint} to be used because it creates confusion" do
|
239
|
+
dbl = double_with_unmet_expectation(:expected_method)
|
240
|
+
expect {
|
241
|
+
expect(dbl).not_to have_received(:expected_method).send(constraint)
|
242
|
+
}.to raise_error(/can't use #{constraint} when negative/)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def double_with_met_expectation(method_name, *args)
|
248
|
+
double = double_with_unmet_expectation(method_name)
|
249
|
+
meet_expectation(double, method_name, *args)
|
250
|
+
end
|
251
|
+
|
252
|
+
def null_object_with_met_expectation(method_name, *args)
|
253
|
+
meet_expectation(double.as_null_object, method_name, *args)
|
254
|
+
end
|
255
|
+
|
256
|
+
def meet_expectation(double, method_name, *args)
|
257
|
+
double.send(method_name, *args)
|
258
|
+
double
|
259
|
+
end
|
260
|
+
|
261
|
+
def double_with_unmet_expectation(method_name)
|
262
|
+
double('double', method_name => true)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
@@ -0,0 +1,318 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module Mocks
|
5
|
+
describe Matchers::Receive do
|
6
|
+
include_context "with syntax", :expect
|
7
|
+
|
8
|
+
def verify_all
|
9
|
+
::RSpec::Mocks.space.verify_all
|
10
|
+
end
|
11
|
+
|
12
|
+
shared_examples_for "a receive matcher" do |*options|
|
13
|
+
it 'allows the caller to configure how the subject responds' do
|
14
|
+
wrapped.to receive(:foo).and_return(5)
|
15
|
+
expect(receiver.foo).to eq(5)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'allows the caller to constrain the received arguments' do
|
19
|
+
wrapped.to receive(:foo).with(:a)
|
20
|
+
receiver.foo(:a)
|
21
|
+
|
22
|
+
expect {
|
23
|
+
receiver.foo(:b)
|
24
|
+
}.to raise_error(/received :foo with unexpected arguments/)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'allows a `do...end` block implementation to be provided' do
|
28
|
+
wrapped.to receive(:foo) do
|
29
|
+
4
|
30
|
+
end
|
31
|
+
|
32
|
+
expect(receiver.foo).to eq(4)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'allows a `{ ... }` block implementation to be provided' do
|
36
|
+
wrapped.to receive(:foo) { 5 }
|
37
|
+
expect(receiver.foo).to eq(5)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'gives precedence to a `{ ... }` block when both forms are provided ' +
|
41
|
+
'since that form actually binds to `receive`' do
|
42
|
+
wrapped.to receive(:foo) { :curly } do
|
43
|
+
:do_end
|
44
|
+
end
|
45
|
+
|
46
|
+
expect(receiver.foo).to eq(:curly)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'does not support other matchers', :unless => options.include?(:allow_other_matchers) do
|
50
|
+
expect {
|
51
|
+
wrapped.to eq(3)
|
52
|
+
}.to raise_error(UnsupportedMatcherError)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
shared_examples_for "an expect syntax allowance" do |*options|
|
57
|
+
include_examples "a receive matcher", *options
|
58
|
+
|
59
|
+
it 'does not expect the message to be received' do
|
60
|
+
wrapped.to receive(:foo)
|
61
|
+
expect { verify_all }.not_to raise_error
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
shared_examples_for "an expect syntax negative allowance" do
|
66
|
+
it 'is disabled since this expression is confusing' do
|
67
|
+
expect {
|
68
|
+
wrapped.not_to receive(:foo)
|
69
|
+
}.to raise_error(/not_to receive` is not supported/)
|
70
|
+
|
71
|
+
expect {
|
72
|
+
wrapped.to_not receive(:foo)
|
73
|
+
}.to raise_error(/to_not receive` is not supported/)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
shared_examples_for "an expect syntax expectation" do |*options|
|
78
|
+
include_examples "a receive matcher", *options
|
79
|
+
|
80
|
+
it 'sets up a message expectation that passes if the message is received' do
|
81
|
+
wrapped.to receive(:foo)
|
82
|
+
receiver.foo
|
83
|
+
verify_all
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'sets up a message expectation that fails if the message is not received' do
|
87
|
+
wrapped.to receive(:foo)
|
88
|
+
|
89
|
+
expect {
|
90
|
+
verify_all
|
91
|
+
}.to raise_error(RSpec::Mocks::MockExpectationError)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "reports the line number of expectation of unreceived message", :pending => options.include?(:does_not_report_line_num) do
|
95
|
+
expected_error_line = __LINE__; wrapped.to receive(:foo)
|
96
|
+
|
97
|
+
expect {
|
98
|
+
verify_all
|
99
|
+
}.to raise_error { |e|
|
100
|
+
expect(e.backtrace.first).to match(/#{File.basename(__FILE__)}:#{expected_error_line}/)
|
101
|
+
}
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
shared_examples_for "an expect syntax negative expectation" do
|
106
|
+
it 'sets up a negaive message expectation that passes if the message is not received' do
|
107
|
+
wrapped.not_to receive(:foo)
|
108
|
+
verify_all
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'sets up a negative message expectation that fails if the message is received' do
|
112
|
+
wrapped.not_to receive(:foo)
|
113
|
+
|
114
|
+
expect {
|
115
|
+
receiver.foo
|
116
|
+
}.to raise_error(/expected: 0 times.*received: 1 time/m)
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'supports `to_not` as an alias for `not_to`' do
|
120
|
+
wrapped.to_not receive(:foo)
|
121
|
+
|
122
|
+
expect {
|
123
|
+
receiver.foo
|
124
|
+
}.to raise_error(/expected: 0 times.*received: 1 time/m)
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'allows the caller to constrain the received arguments' do
|
128
|
+
wrapped.not_to receive(:foo).with(:a)
|
129
|
+
def receiver.method_missing(*a); end # a poor man's stub...
|
130
|
+
|
131
|
+
expect {
|
132
|
+
receiver.foo(:b)
|
133
|
+
}.not_to raise_error
|
134
|
+
|
135
|
+
expect {
|
136
|
+
receiver.foo(:a)
|
137
|
+
}.to raise_error(/expected: 0 times.*received: 1 time/m)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe "allow(...).to receive" do
|
142
|
+
include_examples "an expect syntax allowance" do
|
143
|
+
let(:receiver) { double }
|
144
|
+
let(:wrapped) { allow(receiver) }
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe "allow(...).not_to receive" do
|
149
|
+
include_examples "an expect syntax negative allowance" do
|
150
|
+
let(:wrapped) { allow(double) }
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe "allow_any_instance_of(...).to receive" do
|
155
|
+
include_examples "an expect syntax allowance" do
|
156
|
+
let(:klass) { Class.new }
|
157
|
+
let(:wrapped) { allow_any_instance_of(klass) }
|
158
|
+
let(:receiver) { klass.new }
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe "allow_any_instance_of(...).not_to receive" do
|
163
|
+
include_examples "an expect syntax negative allowance" do
|
164
|
+
let(:wrapped) { allow_any_instance_of(Class.new) }
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
describe "expect(...).to receive" do
|
169
|
+
include_examples "an expect syntax expectation", :allow_other_matchers do
|
170
|
+
let(:receiver) { double }
|
171
|
+
let(:wrapped) { expect(receiver) }
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
describe "expect_any_instance_of(...).to receive" do
|
176
|
+
include_examples "an expect syntax expectation", :does_not_report_line_num do
|
177
|
+
let(:klass) { Class.new }
|
178
|
+
let(:wrapped) { expect_any_instance_of(klass) }
|
179
|
+
let(:receiver) { klass.new }
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
describe "expect(...).not_to receive" do
|
184
|
+
include_examples "an expect syntax negative expectation" do
|
185
|
+
let(:receiver) { double }
|
186
|
+
let(:wrapped) { expect(receiver) }
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
describe "expect_any_instance_of(...).not_to receive" do
|
191
|
+
include_examples "an expect syntax negative expectation" do
|
192
|
+
let(:klass) { Class.new }
|
193
|
+
let(:wrapped) { expect_any_instance_of(klass) }
|
194
|
+
let(:receiver) { klass.new }
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
shared_examples "using rspec-mocks in another test framework" do
|
199
|
+
it 'can use the `expect` syntax' do
|
200
|
+
dbl = double
|
201
|
+
|
202
|
+
framework.new.instance_eval do
|
203
|
+
expect(dbl).to receive(:foo).and_return(3)
|
204
|
+
end
|
205
|
+
|
206
|
+
expect(dbl.foo).to eq(3)
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'expects the method to be called when `expect` is used' do
|
210
|
+
dbl = double
|
211
|
+
|
212
|
+
framework.new.instance_eval do
|
213
|
+
expect(dbl).to receive(:foo)
|
214
|
+
end
|
215
|
+
|
216
|
+
expect { verify dbl }.to raise_error(RSpec::Mocks::MockExpectationError)
|
217
|
+
end
|
218
|
+
|
219
|
+
it 'supports `expect(...).not_to receive`' do
|
220
|
+
dbl = double
|
221
|
+
|
222
|
+
framework.new.instance_eval do
|
223
|
+
expect(dbl).not_to receive(:foo)
|
224
|
+
end
|
225
|
+
|
226
|
+
expect { dbl.foo }.to raise_error(RSpec::Mocks::MockExpectationError)
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'supports `expect(...).to_not receive`' do
|
230
|
+
dbl = double
|
231
|
+
|
232
|
+
framework.new.instance_eval do
|
233
|
+
expect(dbl).to_not receive(:foo)
|
234
|
+
end
|
235
|
+
|
236
|
+
expect { dbl.foo }.to raise_error(RSpec::Mocks::MockExpectationError)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
context "when used in a test framework without rspec-expectations" do
|
241
|
+
let(:framework) do
|
242
|
+
Class.new do
|
243
|
+
include RSpec::Mocks::ExampleMethods
|
244
|
+
|
245
|
+
def eq(value)
|
246
|
+
double("MyMatcher")
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
include_examples "using rspec-mocks in another test framework"
|
252
|
+
|
253
|
+
it 'cannot use `expect` with another matcher' do
|
254
|
+
expect {
|
255
|
+
framework.new.instance_eval do
|
256
|
+
expect(3).to eq(3)
|
257
|
+
end
|
258
|
+
}.to raise_error(/only the `receive` matcher is supported/)
|
259
|
+
end
|
260
|
+
|
261
|
+
it 'can toggle the available syntax' do
|
262
|
+
expect(framework.new).to respond_to(:expect)
|
263
|
+
RSpec::Mocks.configuration.syntax = :should
|
264
|
+
expect(framework.new).not_to respond_to(:expect)
|
265
|
+
RSpec::Mocks.configuration.syntax = :expect
|
266
|
+
expect(framework.new).to respond_to(:expect)
|
267
|
+
end
|
268
|
+
|
269
|
+
after { RSpec::Mocks.configuration.syntax = :expect }
|
270
|
+
end
|
271
|
+
|
272
|
+
context "when rspec-expectations is included in the test framework first" do
|
273
|
+
before do
|
274
|
+
# the examples here assume `expect` is define in RSpec::Matchers...
|
275
|
+
expect(RSpec::Matchers.method_defined?(:expect)).to be_true
|
276
|
+
end
|
277
|
+
|
278
|
+
let(:framework) do
|
279
|
+
Class.new do
|
280
|
+
include RSpec::Matchers
|
281
|
+
include RSpec::Mocks::ExampleMethods
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
include_examples "using rspec-mocks in another test framework"
|
286
|
+
|
287
|
+
it 'can use `expect` with any matcher' do
|
288
|
+
framework.new.instance_eval do
|
289
|
+
expect(3).to eq(3)
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
context "when rspec-expectations is included in the test framework last" do
|
295
|
+
before do
|
296
|
+
# the examples here assume `expect` is define in RSpec::Matchers...
|
297
|
+
expect(RSpec::Matchers.method_defined?(:expect)).to be_true
|
298
|
+
end
|
299
|
+
|
300
|
+
let(:framework) do
|
301
|
+
Class.new do
|
302
|
+
include RSpec::Mocks::ExampleMethods
|
303
|
+
include RSpec::Matchers
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
include_examples "using rspec-mocks in another test framework"
|
308
|
+
|
309
|
+
it 'can use `expect` with any matcher' do
|
310
|
+
framework.new.instance_eval do
|
311
|
+
expect(3).to eq(3)
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|