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