-
Notifications
You must be signed in to change notification settings - Fork 26
/
rspec_examples_spec.rb
244 lines (181 loc) · 6.44 KB
/
rspec_examples_spec.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
RSpec.configure do |config|
config.mock_with :flexmock
end
describe "Simple Spec" do
# Simple stubbing of some methods
it "stubs a couple of methods" do
m = flexmock(:pi => 3.1416, :e => 2.71)
m.pi.should == 3.1416
m.e.should == 2.71
end
end
describe "Returning Undefined" do
# Create a mock object that returns an undefined object for method calls
it "returns undefined values" do
m = flexmock("mock")
m.should_receive(:divide_by).with(0).
and_return_undefined
m.divide_by(0).should == FlexMock.undefined
end
end
describe "Multiple Queries and Single Updates" do
# Expect multiple queries and a single update
# Multiple calls to the query method will be allows, and calls may
# have any argument list. Each call to query will return the three
# element array [1, 2, 3]. The call to update must have a specific
# argument of 5.
it "queries the db" do
db = flexmock('db')
db.should_receive(:query).and_return([1,2,3])
db.should_receive(:update).with(5).and_return(nil).once
# Test Code
db.query
db.update(5)
end
end
describe "Ordered Mocks" do
# Expect all queries before any updates
# All the query message must occur before any of the update
# messages.
it "queries and updates the database" do
db = flexmock('db')
db.should_receive(:query).and_return([1,2,3]).ordered
db.should_receive(:update).and_return(nil).ordered
# test code here
db.query
db.update
end
end
describe "Ordered Mocks" do
# Expect several queries with different parameters
# The queries should happen after startup but before finish. The
# queries themselves may happen in any order (because they are in
# the same order group). The first two queries should happen exactly
# once, but the third query (which matches any query call with a
# four character parameter) may be called multiple times (but at
# least once). Startup and finish must also happen exactly once.
# Also note that we use the <code>with</code> method to match
# different argument values to figure out what value to return.
it "queries the database in a particular order" do
db = flexmock('db')
db.should_receive(:startup).once.ordered
db.should_receive(:query).with("CPWR").and_return(12.3).
once.ordered(:queries)
db.should_receive(:query).with("MSFT").and_return(10.0).
once.ordered(:queries)
db.should_receive(:query).with(/^....$/).and_return(3.3).
at_least.once.ordered(:queries)
db.should_receive(:finish).once.ordered
# Test Code
db.startup
db.query("MSFT")
db.query("XYZY")
db.query("CPWR")
db.finish
end
end
describe "Ordered Mocks" do
# Same as above, but using the Record Mode interface
# The record mode interface offers much the same features as the
# <code>should_receive</code> interface introduced so far, but it
# allows the messages to be sent directly to a recording object
# rather than be specified indirectly using a symbol.
it "records the queries for replay" do
db = flexmock('db')
db.should_expect do |rec|
rec.startup.once.ordered
rec.query("CPWR") { 12.3 }.once.ordered(:queries)
rec.query("MSFT") { 10.0 }.once.ordered(:queries)
rec.query(/^....$/) { 3.3 }.at_least.once.ordered(:queries)
rec.finish.once.ordered
end
# Test Code
db.startup
db.query("MSFT")
db.query("XYZY")
db.query("CPWR")
db.finish
end
end
describe "Record Mode" do
# Using Record Mode to record a known, good algorithm for testing
# Record mode is nice when you have a known, good algorithm that can
# use a recording mock object to record the steps. Then you compare
# the execution of a new algorithm to behavior of the old using the
# recorded expectations in the mock. For this you probably want to
# put the recorder in _strict_ mode so that the recorded
# expectations use exact matching on argument lists, and strict
# ordering of the method calls.
# <b>Note:</b> This is most useful when there are no queries on the
# mock objects, because the query responses cannot be programmed
# into the recorder object.
it "compares a know algorithm with a new algorithm" do
builder = flexmock('builder')
builder.should_expect do |rec|
rec.should_be_strict
known_good_way_to_build_xml(rec) # record the messages
end
new_way_to_build_xml(builder) # compare to new way
end
def known_good_way_to_build_xml(builder)
builder.person
end
def new_way_to_build_xml(builder)
builder.person
end
end
describe "Multiple Return Values" do
# Expect multiple calls, returning a different value each time
# Sometimes you need to return different values for each call to a
# mocked method. This example shifts values out of a list for this
# effect.
it "returns multiple values" do
file = flexmock('file')
file.should_receive(:gets).with_no_args.
and_return("line 1\n", "line 2\n")
# test code here
file.gets # returns "line 1"
file.gets # returns "line 2"
end
end
describe "Ignore Unimportant Messages" do
# Ignore uninteresting messages
# Generally you need to mock only those methods that return an
# interesting value or wish to assert were sent in a particular
# manner. Use the <code>should_ignore_missing</code> method to turn
# on missing method ignoring.
it "ignores unimportant messages" do
m = flexmock('m')
m.should_receive(:an_important_message).and_return(1).once
m.should_ignore_missing
# Test Code
m.an_important_message
m.an_unimportant_message
end
# When <code>should_ignore_missing</code> is enabled, ignored
# missing methods will return an undefined object. Any operation on
# the undefined object will return the undefined object.
end
describe "Partial Mocks" do
# Mock just one method on an existing object
# The Portfolio class calculate the value of a set of stocks by
# talking to a quote service via a web service. Since we don't want
# to use a real web service in our unit tests, we will mock the
# quote service.
it "returns the portfolio value" do
flexmock(QuoteService).new_instances do |m|
m.should_receive(:quote).and_return(100)
end
port = Portfolio.new
value = port.value # Portfolio calls QuoteService.quote
value.should == 100
end
class QuoteService
end
class Portfolio
def value
qs = QuoteService.new
qs.quote
end
end
end