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
|