rspec-mocks 2.8.0.rc1 → 2.8.0.rc2
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/License.txt +23 -0
- data/README.md +238 -21
- data/lib/rspec/mocks.rb +16 -173
- data/lib/rspec/mocks/any_instance.rb +19 -3
- data/lib/rspec/mocks/any_instance/chain.rb +115 -6
- data/lib/rspec/mocks/any_instance/message_chains.rb +35 -23
- data/lib/rspec/mocks/any_instance/recorder.rb +74 -49
- data/lib/rspec/mocks/argument_expectation.rb +1 -0
- data/lib/rspec/mocks/argument_matchers.rb +42 -39
- data/lib/rspec/mocks/error_generator.rb +25 -15
- data/lib/rspec/mocks/errors.rb +2 -0
- data/lib/rspec/mocks/{spec_methods.rb → example_methods.rb} +12 -11
- data/lib/rspec/mocks/extensions/instance_exec.rb +3 -0
- data/lib/rspec/mocks/message_expectation.rb +275 -131
- data/lib/rspec/mocks/method_double.rb +32 -7
- data/lib/rspec/mocks/methods.rb +82 -30
- data/lib/rspec/mocks/mock.rb +7 -5
- data/lib/rspec/mocks/order_group.rb +9 -5
- data/lib/rspec/mocks/proxy.rb +33 -12
- data/lib/rspec/mocks/serialization.rb +4 -0
- data/lib/rspec/mocks/space.rb +1 -0
- data/lib/rspec/mocks/version.rb +1 -1
- data/spec/rspec/mocks/{hash_not_including_matcher_spec.rb → hash_excluding_matcher_spec.rb} +2 -2
- data/spec/rspec/mocks/stub_spec.rb +12 -9
- metadata +15 -15
- data/lib/rspec/mocks/any_instance/expectation_chain.rb +0 -33
- data/lib/rspec/mocks/any_instance/stub_chain.rb +0 -35
- data/lib/rspec/mocks/any_instance/stub_chain_chain.rb +0 -34
data/License.txt
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
(The MIT License)
|
2
|
+
|
3
|
+
Copyright (c) 2006 David Chelimsky, The RSpec Development Team
|
4
|
+
Copyright (c) 2005 Steven Baker
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
a copy of this software and associated documentation files (the
|
8
|
+
"Software"), to deal in the Software without restriction, including
|
9
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be
|
15
|
+
included in all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
20
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
21
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
22
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
23
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,37 +1,254 @@
|
|
1
1
|
# RSpec Mocks
|
2
2
|
|
3
|
-
rspec-mocks
|
4
|
-
|
3
|
+
rspec-mocks is a test-double framework for rspec with support for method stubs,
|
4
|
+
fakes, and message expectations on generated test-doubles and real objects
|
5
|
+
alike.
|
5
6
|
|
6
7
|
## Install
|
7
8
|
|
8
9
|
gem install rspec # for rspec-core, rspec-expectations, rspec-mocks
|
9
10
|
gem install rspec-mocks # for rspec-mocks only
|
10
11
|
|
12
|
+
## Test Doubles
|
13
|
+
|
14
|
+
A Test Double is an object that stands in for a real object in a test.
|
15
|
+
RSpec creates test doubles that support method stubs and message
|
16
|
+
expectations.
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
book = double("book")
|
20
|
+
```
|
21
|
+
|
11
22
|
## Method Stubs
|
12
23
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
24
|
+
A method stub is an implementation that returns a pre-determined value. Method
|
25
|
+
stubs can be declared on test doubles or real objects using the same syntax.
|
26
|
+
rspec-mocks supports 3 forms for declaring method stubs:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
book.stub(:title) { "The RSpec Book" }
|
30
|
+
book.stub(:title => "The RSpec Book")
|
31
|
+
book.stub(:title).and_return("The RSpec Book")
|
32
|
+
```
|
33
|
+
|
34
|
+
You can also use this shortcut, which creates a test double and declares a
|
35
|
+
method stub in one statement:
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
book = double("book", :title => "The RSpec Book")
|
39
|
+
```
|
40
|
+
|
41
|
+
The first argment is a name, which is used for documentation and appears in
|
42
|
+
failure messages. If you don't care about the name, you can leave it out,
|
43
|
+
making the combined instantiation/stub declaration very terse:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
double(:foo => 'bar')
|
47
|
+
```
|
48
|
+
|
49
|
+
This is particularly nice when providing a list of test doubles to a method
|
50
|
+
that iterates through them:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
order.calculate_total_price(stub(:price => 1.99),stub(:price => 2.99))
|
54
|
+
```
|
55
|
+
|
56
|
+
## Consecutive return values
|
57
|
+
|
58
|
+
When a stub might be invoked more than once, you can provide additional
|
59
|
+
arguments to `and_return`. The invocations cycle through the list. The last
|
60
|
+
value is returned for any subsequent invocations:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
die.stub(:roll).and_return(1,2,3)
|
64
|
+
die.roll # => 1
|
65
|
+
die.roll # => 2
|
66
|
+
die.roll # => 3
|
67
|
+
die.roll # => 3
|
68
|
+
die.roll # => 3
|
69
|
+
```
|
70
|
+
|
71
|
+
To return an array in a single invocation, declare an array:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
team.stub(:players).and_return([stub(:name => "David")])
|
75
|
+
```
|
22
76
|
|
23
77
|
## Message Expectations
|
24
78
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
79
|
+
A message expectation is an expectation that the test double will receive a
|
80
|
+
message some time before the example ends. If the message is received, the
|
81
|
+
expectation is satisfied. If not, the example fails.
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
validator = double("validator")
|
85
|
+
validator.should_receive(:validate).with("02134")
|
86
|
+
zipcode = Zipcode.new("02134", validator)
|
87
|
+
zipcode.valid?
|
88
|
+
```
|
89
|
+
|
90
|
+
## Nomenclature
|
91
|
+
|
92
|
+
### Mock Objects and Test Stubs
|
93
|
+
|
94
|
+
The names Mock Object and Test Stub suggest specialized Test Doubles. i.e.
|
95
|
+
a Test Stub is a Test Double that only supports method stubs, and a Mock
|
96
|
+
Object is a Test Double that supports message expectations and method
|
97
|
+
stubs.
|
98
|
+
|
99
|
+
There is a lot of overlapping nomenclature here, and there are many
|
100
|
+
variations of these patterns (fakes, spies, etc). Keep in mind that most of
|
101
|
+
the time we're talking about method-level concepts that are variations of
|
102
|
+
method stubs and message expectations, and we're applying to them to _one_
|
103
|
+
generic kind of object: a Test Double.
|
104
|
+
|
105
|
+
### Test-Specific Extension
|
106
|
+
|
107
|
+
a.k.a. Partial Stub/Mock, a Test-Specific Extension is an extension of a
|
108
|
+
real object in a system that is instrumented with test-double like
|
109
|
+
behaviour in the context of a test. This technique is very common in Ruby
|
110
|
+
because we often see class objects acting as global namespaces for methods.
|
111
|
+
For example, in Rails:
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
person = double("person")
|
115
|
+
Person.stub(:find) { person }
|
116
|
+
```
|
117
|
+
|
118
|
+
In this case we're instrumenting Person to return the person object we've
|
119
|
+
defined whenever it receives the `find` message. We can do this with any
|
120
|
+
object in a system because rspec-mocks adds the `stub` and `should_receive`
|
121
|
+
methods to every object. When we use either, RSpec replaces the method
|
122
|
+
we're stubbing or mocking with its own test-double-like method. At the
|
123
|
+
end of the example, RSpec verifies any message expectations, and then
|
124
|
+
restores the original methods.
|
125
|
+
|
126
|
+
## Expecting Arguments
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
double.should_receive(:msg).with(*args)
|
130
|
+
double.should_not_receive(:msg).with(*args)
|
131
|
+
```
|
132
|
+
|
133
|
+
## Argument Matchers
|
134
|
+
|
135
|
+
Arguments that are passed to `with` are compared with actual arguments
|
136
|
+
received using ==. In cases in which you want to specify things about the
|
137
|
+
arguments rather than the arguments themselves, you can use any of the
|
138
|
+
matchers that ship with rspec-expectations. They don't all make syntactic
|
139
|
+
sense (they were primarily designed for use with RSpec::Expectations), but
|
140
|
+
you are free to create your own custom RSpec::Matchers.
|
141
|
+
|
142
|
+
rspec-mocks also adds some keyword Symbols that you can use to
|
143
|
+
specify certain kinds of arguments:
|
144
|
+
|
145
|
+
```ruby
|
146
|
+
double.should_receive(:msg).with(no_args())
|
147
|
+
double.should_receive(:msg).with(any_args())
|
148
|
+
double.should_receive(:msg).with(1, kind_of(Numeric), "b") #2nd argument can any kind of Numeric
|
149
|
+
double.should_receive(:msg).with(1, boolean(), "b") #2nd argument can true or false
|
150
|
+
double.should_receive(:msg).with(1, /abc/, "b") #2nd argument can be any String matching the submitted Regexp
|
151
|
+
double.should_receive(:msg).with(1, anything(), "b") #2nd argument can be anything at all
|
152
|
+
double.should_receive(:msg).with(1, ducktype(:abs, :div), "b")
|
153
|
+
#2nd argument can be object that responds to #abs and #div
|
154
|
+
```
|
155
|
+
|
156
|
+
## Receive Counts
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
double.should_receive(:msg).once
|
160
|
+
double.should_receive(:msg).twice
|
161
|
+
double.should_receive(:msg).exactly(n).times
|
162
|
+
double.should_receive(:msg).at_least(:once)
|
163
|
+
double.should_receive(:msg).at_least(:twice)
|
164
|
+
double.should_receive(:msg).at_least(n).times
|
165
|
+
double.should_receive(:msg).at_most(:once)
|
166
|
+
double.should_receive(:msg).at_most(:twice)
|
167
|
+
double.should_receive(:msg).at_most(n).times
|
168
|
+
double.should_receive(:msg).any_number_of_times
|
169
|
+
```
|
170
|
+
|
171
|
+
## Ordering
|
172
|
+
|
173
|
+
```ruby
|
174
|
+
double.should_receive(:msg).ordered
|
175
|
+
double.should_receive(:other_msg).ordered
|
176
|
+
#This will fail if the messages are received out of order
|
177
|
+
```
|
178
|
+
|
179
|
+
## Setting Reponses
|
180
|
+
|
181
|
+
Whether you are setting a message expectation or a method stub, you can
|
182
|
+
tell the object precisely how to respond. The most generic way is to pass
|
183
|
+
a block to `stub` or `should_receive`:
|
184
|
+
|
185
|
+
```ruby
|
186
|
+
double.should_receive(:msg) { value }
|
187
|
+
```
|
188
|
+
|
189
|
+
When the double receives the `msg` message, it evaluates the block and returns
|
190
|
+
the result.
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
double.should_receive(:msg).and_return(value)
|
194
|
+
double.should_receive(:msg).exactly(3).times.and_return(value1, value2, value3)
|
195
|
+
# returns value1 the first time, value2 the second, etc
|
196
|
+
double.should_receive(:msg).and_raise(error)
|
197
|
+
#error can be an instantiated object or a class
|
198
|
+
#if it is a class, it must be instantiable with no args
|
199
|
+
double.should_receive(:msg).and_throw(:msg)
|
200
|
+
double.should_receive(:msg).and_yield(values,to,yield)
|
201
|
+
double.should_receive(:msg).and_yield(values,to,yield).and_yield(some,other,values,this,time)
|
202
|
+
# for methods that yield to a block multiple times
|
203
|
+
```
|
204
|
+
|
205
|
+
Any of these responses can be applied to a stub as well
|
206
|
+
|
207
|
+
```ruby
|
208
|
+
double.stub(:msg).and_return(value)
|
209
|
+
double.stub(:msg).and_return(value1, value2, value3)
|
210
|
+
double.stub(:msg).and_raise(error)
|
211
|
+
double.stub(:msg).and_throw(:msg)
|
212
|
+
double.stub(:msg).and_yield(values,to,yield)
|
213
|
+
double.stub(:msg).and_yield(values,to,yield).and_yield(some,other,values,this,time)
|
214
|
+
```
|
215
|
+
|
216
|
+
## Arbitrary Handling
|
217
|
+
|
218
|
+
Once in a while you'll find that the available expectations don't solve the
|
219
|
+
particular problem you are trying to solve. Imagine that you expect the message
|
220
|
+
to come with an Array argument that has a specific length, but you don't care
|
221
|
+
what is in it. You could do this:
|
222
|
+
|
223
|
+
```ruby
|
224
|
+
double.should_receive(:msg) do |arg|
|
225
|
+
arg.size.should eq(7)
|
226
|
+
end
|
227
|
+
```
|
228
|
+
|
229
|
+
## Combining Expectation Details
|
230
|
+
|
231
|
+
Combining the message name with specific arguments, receive counts and responses
|
232
|
+
you can get quite a bit of detail in your expectations:
|
233
|
+
|
234
|
+
```ruby
|
235
|
+
double.should_receive(:<<).with("illegal value").once.and_raise(ArgumentError)
|
236
|
+
```
|
237
|
+
|
238
|
+
While this is a good thing when you really need it, you probably don't really
|
239
|
+
need it! Take care to specify only the things that matter to the behavior of
|
240
|
+
your code.
|
241
|
+
|
242
|
+
## Further Reading
|
243
|
+
|
244
|
+
There are many different viewpoints about the meaning of mocks and stubs. If
|
245
|
+
you are interested in learning more, here is some recommended reading:
|
246
|
+
|
247
|
+
* Mock Objects: http://www.mockobjects.com/
|
248
|
+
* Endo-Testing: http://www.mockobjects.com/files/endotesting.pdf
|
249
|
+
* Mock Roles, Not Objects: http://www.mockobjects.com/files/mockrolesnotobjects.pdf
|
250
|
+
* Test Double Patterns: http://xunitpatterns.com/Test%20Double%20Patterns.html
|
251
|
+
* Mocks aren't stubs: http://www.martinfowler.com/articles/mocksArentStubs.html
|
35
252
|
|
36
253
|
## Also see
|
37
254
|
|
data/lib/rspec/mocks.rb
CHANGED
@@ -1,184 +1,15 @@
|
|
1
1
|
require 'rspec/mocks/framework'
|
2
2
|
require 'rspec/mocks/version'
|
3
|
-
require 'rspec/mocks/
|
3
|
+
require 'rspec/mocks/example_methods'
|
4
4
|
|
5
5
|
module RSpec
|
6
|
-
# == Test Doubles
|
7
|
-
#
|
8
|
-
# A Test Double is an object that stands in for a real object in a test.
|
9
|
-
# RSpec creates test doubles that support method stubs and message
|
10
|
-
# expectations.
|
11
|
-
#
|
12
|
-
# book = double("book")
|
13
|
-
#
|
14
|
-
# == Method Stubs
|
15
|
-
#
|
16
|
-
# A method stub is an implementation that returns a pre-determined value.
|
17
|
-
#
|
18
|
-
# book = double("book")
|
19
|
-
# double.stub(:title) { "The RSpec Book" }
|
20
|
-
# double.title # => "The RSpec Book"
|
21
|
-
#
|
22
|
-
# When we declare a stub, we say we are "stubbing" a method.
|
23
|
-
#
|
24
|
-
# == Message Expectations
|
25
|
-
#
|
26
|
-
# A message expectation is an expectation that the test double will receive a
|
27
|
-
# message some time before the example ends. If the message is received, the
|
28
|
-
# expectation is satisfied. If not, the example fails.
|
29
|
-
#
|
30
|
-
# validator = double("validator")
|
31
|
-
# validator.should_receive(:validate).with("02134")
|
32
|
-
# zipcode = Zipcode.new("02134", validator)
|
33
|
-
# zipcode.valid?
|
34
|
-
#
|
35
|
-
# When we declare a message expectation, we say we are "mocking" a method.
|
36
|
-
#
|
37
|
-
# == Mock Objects and Test Stubs
|
38
|
-
#
|
39
|
-
# The names Mock Object and Test Stub suggest specialized Test Doubles. i.e.
|
40
|
-
# a Test Stub is a Test Double that only supports method stubs, and a Mock
|
41
|
-
# Object is a Test Double that supports message expectations and method
|
42
|
-
# stubs.
|
43
|
-
#
|
44
|
-
# There is a lot of overlapping nomenclature here, and there are many
|
45
|
-
# variations of these patterns (fakes, spies, etc). Keep in mind that most of
|
46
|
-
# the time we're talking about method-level concepts that are variations of
|
47
|
-
# method stubs and message expectations, and we're applying to them to _one_
|
48
|
-
# generic kind of object: a Test Double.
|
49
|
-
#
|
50
|
-
# == Test-Specific Extension
|
51
|
-
#
|
52
|
-
# a.k.a. Partial Stub/Mock, a Test-Specific Extension is an extension of a
|
53
|
-
# real object in a system that is instrumented with test-double like
|
54
|
-
# behaviour in the context of a test. This technique is very common in Ruby
|
55
|
-
# because we often see class objects acting as global namespaces for methods.
|
56
|
-
# For example, in Rails:
|
57
|
-
#
|
58
|
-
# person = double("person")
|
59
|
-
# Person.stub(:find) { person }
|
60
|
-
#
|
61
|
-
# In this case we're instrumenting Person to return the person object we've
|
62
|
-
# defined whenever it receives the +find+ message. We can do this with any
|
63
|
-
# object in a system because rspec-mocks adds the +stub+ and +should_receive+
|
64
|
-
# methods to every object. When we use either, RSpec replaces the method
|
65
|
-
# we're stubbing or mocking with it's own test-double-like method. At the
|
66
|
-
# end of the example, RSpec verifies any message expectations, and then
|
67
|
-
# restores the original methods.
|
68
|
-
#
|
69
|
-
# == Expecting Arguments
|
70
|
-
#
|
71
|
-
# double.should_receive(:msg).with(*args)
|
72
|
-
# double.should_not_receive(:msg).with(*args)
|
73
|
-
#
|
74
|
-
# == Argument Matchers
|
75
|
-
#
|
76
|
-
# Arguments that are passed to +with+ are compared with actual arguments
|
77
|
-
# received using ==. In cases in which you want to specify things about the
|
78
|
-
# arguments rather than the arguments themselves, you can use any of the
|
79
|
-
# matchers that ship with rspec-expectations. They don't all make syntactic
|
80
|
-
# sense (they were primarily designed for use with RSpec::Expectations), but
|
81
|
-
# you are free to create your own custom RSpec::Matchers.
|
82
|
-
#
|
83
|
-
# rspec-mocks also adds some keyword Symbols that you can use to
|
84
|
-
# specify certain kinds of arguments:
|
85
|
-
#
|
86
|
-
# double.should_receive(:msg).with(no_args())
|
87
|
-
# double.should_receive(:msg).with(any_args())
|
88
|
-
# double.should_receive(:msg).with(1, kind_of(Numeric), "b") #2nd argument can any kind of Numeric
|
89
|
-
# double.should_receive(:msg).with(1, boolean(), "b") #2nd argument can true or false
|
90
|
-
# double.should_receive(:msg).with(1, /abc/, "b") #2nd argument can be any String matching the submitted Regexp
|
91
|
-
# double.should_receive(:msg).with(1, anything(), "b") #2nd argument can be anything at all
|
92
|
-
# double.should_receive(:msg).with(1, ducktype(:abs, :div), "b")
|
93
|
-
# #2nd argument can be object that responds to #abs and #div
|
94
|
-
#
|
95
|
-
# == Receive Counts
|
96
|
-
#
|
97
|
-
# double.should_receive(:msg).once
|
98
|
-
# double.should_receive(:msg).twice
|
99
|
-
# double.should_receive(:msg).exactly(n).times
|
100
|
-
# double.should_receive(:msg).at_least(:once)
|
101
|
-
# double.should_receive(:msg).at_least(:twice)
|
102
|
-
# double.should_receive(:msg).at_least(n).times
|
103
|
-
# double.should_receive(:msg).at_most(:once)
|
104
|
-
# double.should_receive(:msg).at_most(:twice)
|
105
|
-
# double.should_receive(:msg).at_most(n).times
|
106
|
-
# double.should_receive(:msg).any_number_of_times
|
107
|
-
#
|
108
|
-
# == Ordering
|
109
|
-
#
|
110
|
-
# double.should_receive(:msg).ordered
|
111
|
-
# double.should_receive(:other_msg).ordered
|
112
|
-
# #This will fail if the messages are received out of order
|
113
|
-
#
|
114
|
-
# == Setting Reponses
|
115
|
-
#
|
116
|
-
# Whether you are setting a message expectation or a method stub, you can
|
117
|
-
# tell the object precisely how to respond. The most generic way is to pass
|
118
|
-
# a block to +stub+ or +should_receive+:
|
119
|
-
#
|
120
|
-
# double.should_receive(:msg) { value }
|
121
|
-
#
|
122
|
-
# When the double receives the +msg+ message, it evaluates the block and returns
|
123
|
-
# the result.
|
124
|
-
#
|
125
|
-
# double.should_receive(:msg).and_return(value)
|
126
|
-
# double.should_receive(:msg).exactly(3).times.and_return(value1, value2, value3)
|
127
|
-
# # returns value1 the first time, value2 the second, etc
|
128
|
-
# double.should_receive(:msg).and_raise(error)
|
129
|
-
# #error can be an instantiated object or a class
|
130
|
-
# #if it is a class, it must be instantiable with no args
|
131
|
-
# double.should_receive(:msg).and_throw(:msg)
|
132
|
-
# double.should_receive(:msg).and_yield(values,to,yield)
|
133
|
-
# double.should_receive(:msg).and_yield(values,to,yield).and_yield(some,other,values,this,time)
|
134
|
-
# # for methods that yield to a block multiple times
|
135
|
-
#
|
136
|
-
# Any of these responses can be applied to a stub as well
|
137
|
-
#
|
138
|
-
# double.stub(:msg).and_return(value)
|
139
|
-
# double.stub(:msg).and_return(value1, value2, value3)
|
140
|
-
# double.stub(:msg).and_raise(error)
|
141
|
-
# double.stub(:msg).and_throw(:msg)
|
142
|
-
# double.stub(:msg).and_yield(values,to,yield)
|
143
|
-
# double.stub(:msg).and_yield(values,to,yield).and_yield(some,other,values,this,time)
|
144
|
-
#
|
145
|
-
# == Arbitrary Handling
|
146
|
-
#
|
147
|
-
# Once in a while you'll find that the available expectations don't solve the
|
148
|
-
# particular problem you are trying to solve. Imagine that you expect the message
|
149
|
-
# to come with an Array argument that has a specific length, but you don't care
|
150
|
-
# what is in it. You could do this:
|
151
|
-
#
|
152
|
-
# double.should_receive(:msg) do |arg|
|
153
|
-
# arg.should be_an_istance_of(Array)
|
154
|
-
# arg.length.should eq 7
|
155
|
-
# end
|
156
|
-
#
|
157
|
-
# == Combining Expectation Details
|
158
|
-
#
|
159
|
-
# Combining the message name with specific arguments, receive counts and responses
|
160
|
-
# you can get quite a bit of detail in your expectations:
|
161
|
-
#
|
162
|
-
# double.should_receive(:<<).with("illegal value").once.and_raise(ArgumentError)
|
163
|
-
#
|
164
|
-
# == Further Reading
|
165
|
-
#
|
166
|
-
# There are many different viewpoints about the meaning of mocks and stubs. If you are interested
|
167
|
-
# in learning more, here is some recommended reading:
|
168
|
-
#
|
169
|
-
# * Mock Objects: http://www.mockobjects.com/
|
170
|
-
# * Endo-Testing: http://www.mockobjects.com/files/endotesting.pdf
|
171
|
-
# * Mock Roles, Not Objects: http://www.mockobjects.com/files/mockrolesnotobjects.pdf
|
172
|
-
# * Test Double Patterns: http://xunitpatterns.com/Test%20Double%20Patterns.html
|
173
|
-
# * Mocks aren't stubs: http://www.martinfowler.com/articles/mocksArentStubs.html
|
174
6
|
module Mocks
|
175
7
|
class << self
|
176
8
|
attr_accessor :space
|
177
9
|
|
178
|
-
def setup(
|
179
|
-
|
180
|
-
|
181
|
-
(class << includer; self; end).class_eval do
|
10
|
+
def setup(host)
|
11
|
+
add_extensions unless extensions_added?
|
12
|
+
(class << host; self; end).class_eval do
|
182
13
|
include RSpec::Mocks::ExampleMethods
|
183
14
|
end
|
184
15
|
self.space ||= RSpec::Mocks::Space.new
|
@@ -191,6 +22,18 @@ module RSpec
|
|
191
22
|
def teardown
|
192
23
|
space.reset_all
|
193
24
|
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def add_extensions
|
29
|
+
Object.class_eval { include RSpec::Mocks::Methods }
|
30
|
+
Class.class_eval { include RSpec::Mocks::AnyInstance }
|
31
|
+
$_rspec_mocks_extensions_added = true
|
32
|
+
end
|
33
|
+
|
34
|
+
def extensions_added?
|
35
|
+
defined?($_rspec_mocks_extensions_added)
|
36
|
+
end
|
194
37
|
end
|
195
38
|
end
|
196
39
|
end
|