Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 298 lines (179 sloc) 9.698 kB
95e8298 Revert "WebMock module has to be included manually and is not include…
Bartosz Blimke authored
1 WebMock
2 =======
3
4 Library for stubbing HTTP requests and setting expectations on HTTP requests in Ruby.
5
6 Features
7 --------
8
9 * Stubbing HTTP requests at low Net::HTTP level (no need to change tests when you change HTTP lib interface)
10 * Setting and verifying expectations on HTTP requests
11 * Matching requests based on method, URI, headers and body
12 * Smart matching of the same URIs in different representations (also encoded and non encoded forms)
13 * Smart matching of the same headers in different representations.
14 * Support for Test::Unit and RSpec (and can be easily extended to other frameworks)
15 * Support for Net::HTTP and other http libraries based on Net::HTTP (i.e RightHttpConnection, rest-client, HTTParty)
16 * Easy to extend to other HTTP libraries except Net::HTTP
17
18 Installation
19 ------------
20
21 gem install webmock --source http://gemcutter.org
22
23 In your `test/test_helper.rb` add these two lines:
24
25 require 'webmock/test_unit'
26
27 include WebMock
28
29 or if you use RSpec add these lines to `spec/spec_helper`:
30
31 require 'webmock/rspec'
32
33 include WebMock
34
feb8ba5 Updated version to 0.7.3
Bartosz Blimke authored
35 You can also use WebMock without RSpec or Test::Unit support:
3ca443e WebMock module has to be included manually and is not included by RSp…
Bartosz Blimke authored
36
37 require 'webmock'
38
39 include WebMock
95e8298 Revert "WebMock module has to be included manually and is not include…
Bartosz Blimke authored
40
41 ## Examples
42
43
44
45 ## Stubbing
46
47
48 ### Stubbed request based on uri only and with the default response
49
50 stub_request(:any, "www.google.com")
51
52 Net::HTTP.get("www.google.com", "/") # ===> Success
53
54 ### Stubbing requests based on method, uri, body and headers
55
56 stub_request(:post, "www.google.com").with(:body => "abc", :headers => { 'Content-Length' => 3 })
57
58 uri = URI.parse("http://www.google.com/")
59 req = Net::HTTP::Post.new(uri.path)
60 req['Content-Length'] = 3
61 res = Net::HTTP.start(uri.host, uri.port) {|http|
62 http.request(req, "abc")
63 } # ===> Success
64
65 ### Matching custom request headers
66
67 stub_request(:any, "www.google.com").
68 with( :headers=>{ 'Header-Name' => 'Header-Value' } ).to_return(:body => "abc", :status => 200)
69
70 uri = URI.parse('http://www.google.com/')
71 req = Net::HTTP::Post.new(uri.path)
72 req['Header-Name'] = 'Header-Value'
73 res = Net::HTTP.start(uri.host, uri.port) {|http|
74 http.request(req, 'abc')
75 } # ===> Success
76
77 ### Stubbing with custom response
78
79 stub_request(:any, "www.google.com").to_return(:body => "abc", :status => 200, :headers => { 'Content-Length' => 3 } )
80
81 Net::HTTP.get("www.google.com", '/') # ===> "abc"
82
83 ### Custom response with body specified as a path to file
84
85 File.open('/tmp/response_body.txt', 'w') { |f| f.puts 'abc' }
86
87 stub_request(:any, "www.google.com").to_return(:body => "/tmp/response_body.txt", :status => 200)
88
89 Net::HTTP.get('www.google.com', '/') # ===> "abc\n"
90
4e0568a Added information about dynamic responses to README
Bartosz Blimke authored
91 ### Custom response with dynamically evaluated response
92
93 stub_request(:any, 'www.example.net').
94 to_return(:body => lambda { |request| request.body })
95
96 RestClient.post('www.example.net', 'abc') # ===> "abc\n"
97
95e8298 Revert "WebMock module has to be included manually and is not include…
Bartosz Blimke authored
98 ### Request with basic authentication
99
100 stub_request(:any, "john:smith@www.google.com")
101
102 Net::HTTP.get(URI.parse('http://john:smith@www.google.com')) # ===> Success
103
104 ### Matching uris using regular expressions
105
106 stub_request(:any, /.*google.*/)
107
108 Net::HTTP.get('www.google.com', '/') # ===> Success
109
110 ### Real requests to network can be allowed or disabled
111
112 WebMock.allow_net_connect!
113
114 stub_request(:any, "www.google.com").to_return(:body => "abc")
115
116 Net::HTTP.get('www.google.com', '/') # ===> "abc"
117
118 Net::HTTP.get('www.something.com', '/') # ===> /.+Something.+/
119
120 WebMock.disable_net_connect!
121
122 Net::HTTP.get('www.something.com', '/') # ===> Failure
123
124
125 ## Setting Expectations
126
127 ### Setting expectations in Test::Unit
128 require 'webmock/test_unit'
129
130 stub_request(:any, "www.google.com")
131
132 uri = URI.parse('http://www.google.com/')
133 req = Net::HTTP::Post.new(uri.path)
134 req['Content-Length'] = 3
135 res = Net::HTTP.start(uri.host, uri.port) {|http|
136 http.request(req, 'abc')
137 }
138
139 assert_requested :post, "http://www.google.com",
140 :headers => {'Content-Length' => 3}, :body => "abc", :times => 1 # ===> Success
141
142 assert_not_requested :get, "http://www.something.com" # ===> Success
143
144 ### Expecting real (not stubbed) requests
145
146 WebMock.allow_net_connect!
147
148 Net::HTTP.get('www.google.com', '/') # ===> Success
149
150 assert_requested :get, "http://www.google.com" # ===> Success
151
152
153 ### Setting expectations in RSpec
154 This style is borrowed from [fakeweb-matcher](http://github.com/freelancing-god/fakeweb-matcher)
155
156 require 'webmock/rspec'
157
158 WebMock.should have_requested(:get, "www.google.com").with(:body => "abc", :headers => {'Content-Length' => 3}).twice
159
160 WebMock.should_not have_requested(:get, "www.something.com")
161
162 ### Different way of setting expectations in RSpec
163
164 request(:post, "www.google.com").with(:body => "abc", :headers => {'Content-Length' => 3}).should have_been_made.once
165
166 request(:post, "www.something.com").should have_been_made.times(3)
167
168 request(:any, "www.example.com").should_not have_been_made
169
170
171 ## Clearing stubs and request history
172
173 If you want to reset all current stubs and history of requests use `WebMock.reset_webmock`
174
175 stub_request(:any, "www.google.com")
176
177 Net::HTTP.get('www.google.com', '/') # ===> Success
178
179 reset_webmock
180
181 Net::HTTP.get('www.google.com', '/') # ===> Failure
182
183 assert_not_requested :get, "www.google.com" # ===> Success
184
185
186 ## Matching requests
187
188 An executed request matches stubbed request if it passes following criteria:
189
4306efa Ability to register and expect requests with empty body.
Bartosz Blimke authored
190 When request URI matches stubbed request URI string or Regexp pattern<br/>
95e8298 Revert "WebMock module has to be included manually and is not include…
Bartosz Blimke authored
191 And request method is the same as stubbed request method or stubbed request method is :any<br/>
4306efa Ability to register and expect requests with empty body.
Bartosz Blimke authored
192 And request body is the same as stubbed request body or stubbed request body is not specified<br/>
193 And request headers match stubbed request headers, or stubbed request headers match a subset of request headers, or stubbed request headers are not specified
95e8298 Revert "WebMock module has to be included manually and is not include…
Bartosz Blimke authored
194
195 ## Precedence of stubs
196
197 Always the last declared stub matching the request will be applied i.e:
198
199 stub_request(:get, "www.google.com").to_return(:body => "abc")
200 stub_request(:get, "www.google.com").to_return(:body => "def")
201
202 Net::HTTP.get('www.google.com', '/') # ====> "def"
203
204 ## Matching URIs
205
206 WebMock will match all different representations of the same URI.
207
208 I.e all the following representations of the URI are equal:
209
210 "www.google.com"
211 "www.google.com/"
212 "www.google.com:80"
213 "www.google.com:80/"
214 "http://www.google.com"
215 "http://www.google.com/"
216 "http://www.google.com:80"
217 "http://www.google.com:80/"
218
219 The following URIs with basic authentication are also equal for WebMock
220
221 "a b:pass@www.google.com"
222 "a b:pass@www.google.com/"
223 "a b:pass@www.google.com:80"
224 "a b:pass@www.google.com:80/"
225 "http://a b:pass@www.google.com"
226 "http://a b:pass@www.google.com/"
227 "http://a b:pass@www.google.com:80"
228 "http://a b:pass@www.google.com:80/"
229 "a%20b:pass@www.google.com"
230 "a%20b:pass@www.google.com/"
231 "a%20b:pass@www.google.com:80"
232 "a%20b:pass@www.google.com:80/"
233 "http://a%20b:pass@www.google.com"
234 "http://a%20b:pass@www.google.com/"
235 "http://a%20b:pass@www.google.com:80"
236 "http://a%20b:pass@www.google.com:80/"
237
238 or these
239
240 "www.google.com/big image.jpg/?a=big image&b=c"
241 "www.google.com/big%20image.jpg/?a=big%20image&b=c"
242 "www.google.com:80/big image.jpg/?a=big image&b=c"
243 "www.google.com:80/big%20image.jpg/?a=big%20image&b=c"
244 "http://www.google.com/big image.jpg/?a=big image&b=c"
245 "http://www.google.com/big%20image.jpg/?a=big%20image&b=c"
246 "http://www.google.com:80/big image.jpg/?a=big image&b=c"
247 "http://www.google.com:80/big%20image.jpg/?a=big%20image&b=c"
248
249
250 If you provide Regexp to match URI, WebMock will try to match it against every valid form of the same url.
251
252 I.e `/.*big image.*/` will match `www.google.com/big%20image.jpg` because it is equivalent of `www.google.com/big image.jpg`
253
254
255 ## Matching headers
256
257 WebMock will match request headers against stubbed request headers in the following situations:
258
259 1. Stubbed request has headers specified and request headers are the same as stubbed headers <br/>
260 i.e stubbed headers: `{ 'Header1' => 'Value1', 'Header1' => 'Value1' }`, requested: `{ 'Header1' => 'Value1', 'Header1' => 'Value1' }`
261
262 2. Stubbed request has headers specified and stubbed request headers are a subset of request headers <br/>
263 i.e stubbed headers: `{ 'Header1' => 'Value1' }`, requested: `{ 'Header1' => 'Value1', 'Header1' => 'Value1' }`
264
265 3. Stubbed request has no headers <br/>
266 i.e stubbed headers: `nil`, requested: `{ 'Header1' => 'Value1', 'Header1' => 'Value1' }`
267
268 WebMock normalises headers and treats all forms of same headers as equal:
269 i.e the following two sets of headers are equal:
270
271 `{ "Header1" => "value1", :content_length => 123, :X_CuStOm_hEAder => :value }`
272
273 `{ :header1 => "value1", "Content-Length" => 123, "x-cuSTOM-HeAder" => "value" }`
274
275
276 ## Bugs and Issues
277
278 Please submit them here [http://github.com/bblimke/webmock/issues](http://github.com/bblimke/webmock/issues)
279
280 ## Suggestions
281
282 If you have any suggestions on how to improve WebMock please send an email to the mailing list [groups.google.com/group/webmock-users](http://groups.google.com/group/webmock-users)
283
284 I'm particularly interested in how the DSL could be improved.
285
286 ## Credits
287
288 Thanks to my fellow [Bambinos](http://new-bamboo.co.uk/) for all the great suggestions!
289
290 Thank you Fakeweb! This library was inspired by [FakeWeb](fakeweb.rubyforge.org).
291 I took couple of solutions from that project. I also copied some code i.e Net:HTTP adapter.
292 Fakeweb architecture unfortunately didn't allow me to extend it easily with the features I needed.
293 I also preferred some things to work differently i.e request stub precedence.
294
295 ## Copyright
296
297 Copyright 2009 Bartosz Blimke. See LICENSE for details.
Something went wrong with that request. Please try again.