webmock 0.7.1 → 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +9 -0
- data/README.md +169 -76
- data/Rakefile +2 -1
- data/VERSION +1 -1
- data/lib/webmock.rb +12 -9
- data/lib/webmock/adapters/rspec.rb +20 -22
- data/lib/webmock/adapters/rspec/matchers.rb +4 -4
- data/lib/webmock/adapters/rspec/webmock_matcher.rb +2 -2
- data/lib/webmock/adapters/test_unit.rb +20 -21
- data/lib/webmock/http_lib_adapters/net_http.rb +51 -15
- data/lib/webmock/request_profile.rb +5 -44
- data/lib/webmock/request_registry.rb +10 -11
- data/lib/webmock/request_signature.rb +44 -0
- data/lib/webmock/request_stub.rb +3 -3
- data/lib/webmock/response.rb +1 -1
- data/lib/webmock/rspec.rb +1 -0
- data/lib/webmock/test_unit.rb +1 -0
- data/lib/webmock/util/hash_counter.rb +16 -8
- data/lib/webmock/util/headers.rb +23 -0
- data/lib/webmock/util/uri.rb +81 -0
- data/lib/webmock/webmock.rb +16 -19
- data/spec/net_http_spec.rb +10 -9
- data/spec/other_net_http_libs_spec.rb +3 -1
- data/spec/request_profile_spec.rb +6 -116
- data/spec/request_registry_spec.rb +12 -17
- data/spec/request_signature_spec.rb +155 -0
- data/spec/request_stub_spec.rb +2 -2
- data/spec/response_spec.rb +1 -1
- data/spec/spec_helper.rb +4 -1
- data/spec/util/hash_counter_spec.rb +4 -4
- data/spec/util/headers_spec.rb +11 -0
- data/spec/util/uri_spec.rb +213 -0
- data/spec/vendor/addressable/lib/addressable/uri.rb +8 -0
- data/spec/vendor/addressable/lib/uri.rb +0 -0
- data/spec/webmock_spec.rb +58 -10
- data/test/test_helper.rb +5 -1
- data/test/test_webmock.rb +11 -6
- data/webmock.gemspec +21 -6
- metadata +28 -6
- data/lib/webmock/url.rb +0 -46
- data/lib/webmock/utility.rb +0 -65
- data/spec/utility_spec.rb +0 -70
data/CHANGELOG
ADDED
data/README.md
CHANGED
@@ -1,82 +1,100 @@
|
|
1
1
|
WebMock
|
2
2
|
=======
|
3
3
|
|
4
|
-
Library for stubbing HTTP requests in Ruby.
|
4
|
+
Library for stubbing HTTP requests and setting expectations on HTTP requests in Ruby.
|
5
5
|
|
6
6
|
Features
|
7
7
|
--------
|
8
8
|
|
9
|
-
* Stubbing requests
|
10
|
-
*
|
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.
|
11
14
|
* Support for Test::Unit and RSpec (and can be easily extended to other frameworks)
|
12
|
-
* Support for Net::
|
13
|
-
*
|
14
|
-
|
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
|
15
17
|
|
16
18
|
Installation
|
17
19
|
------------
|
18
20
|
|
19
21
|
gem install webmock --source http://gemcutter.org
|
20
22
|
|
21
|
-
In your `test/test_helper.rb`
|
23
|
+
In your `test/test_helper.rb` add these two lines:
|
22
24
|
|
23
|
-
require 'webmock'
|
25
|
+
require 'webmock/test_unit'
|
24
26
|
|
25
27
|
include WebMock
|
26
28
|
|
27
|
-
|
29
|
+
or if you use RSpec add these lines to `spec/spec_helper`:
|
30
|
+
|
31
|
+
require 'webmock/rspec'
|
32
|
+
|
33
|
+
include WebMock
|
34
|
+
|
35
|
+
You can also use WebMock without RSpec or Test::Unit support:
|
36
|
+
|
37
|
+
require 'webmock'
|
38
|
+
|
39
|
+
include WebMock
|
28
40
|
|
29
41
|
## Examples
|
30
42
|
|
31
|
-
|
43
|
+
|
44
|
+
|
45
|
+
## Stubbing
|
46
|
+
|
47
|
+
|
48
|
+
### Stubbed request based on uri only and with the default response
|
32
49
|
|
33
50
|
stub_request(:any, "www.google.com")
|
34
51
|
|
35
|
-
Net::HTTP.get(
|
36
|
-
|
37
|
-
### Stubbing requests based on method,
|
52
|
+
Net::HTTP.get("www.google.com", "/") # ===> Success
|
53
|
+
|
54
|
+
### Stubbing requests based on method, uri, body and headers
|
38
55
|
|
39
56
|
stub_request(:post, "www.google.com").with(:body => "abc", :headers => { 'Content-Length' => 3 })
|
40
57
|
|
41
|
-
|
42
|
-
req = Net::HTTP::Post.new(
|
58
|
+
uri = URI.parse("http://www.google.com/")
|
59
|
+
req = Net::HTTP::Post.new(uri.path)
|
43
60
|
req['Content-Length'] = 3
|
44
|
-
res = Net::HTTP.start(
|
45
|
-
http.request(req,
|
61
|
+
res = Net::HTTP.start(uri.host, uri.port) {|http|
|
62
|
+
http.request(req, "abc")
|
46
63
|
} # ===> Success
|
47
64
|
|
48
65
|
### Matching custom request headers
|
49
66
|
|
50
|
-
stub_request(:any, "www.google.com").
|
67
|
+
stub_request(:any, "www.google.com").
|
68
|
+
with( :headers=>{ 'Header-Name' => 'Header-Value' } ).to_return(:body => "abc", :status => 200)
|
51
69
|
|
52
|
-
|
53
|
-
req = Net::HTTP::Post.new(
|
54
|
-
req['Header-Name'] =
|
55
|
-
res = Net::HTTP.start(
|
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|
|
56
74
|
http.request(req, 'abc')
|
57
75
|
} # ===> Success
|
58
76
|
|
59
|
-
###
|
77
|
+
### Stubbing with custom response
|
60
78
|
|
61
|
-
stub_request(:any, "www.google.com").to_return(:body => "abc", :status => 200, :headers => { 'Content-Length' => 3 })
|
79
|
+
stub_request(:any, "www.google.com").to_return(:body => "abc", :status => 200, :headers => { 'Content-Length' => 3 } )
|
62
80
|
|
63
|
-
Net::HTTP.get(
|
64
|
-
|
65
|
-
### Custom response with body as
|
81
|
+
Net::HTTP.get("www.google.com", '/') # ===> "abc"
|
82
|
+
|
83
|
+
### Custom response with body specified as a path to file
|
66
84
|
|
67
85
|
File.open('/tmp/response_body.txt', 'w') { |f| f.puts 'abc' }
|
68
86
|
|
69
87
|
stub_request(:any, "www.google.com").to_return(:body => "/tmp/response_body.txt", :status => 200)
|
70
88
|
|
71
89
|
Net::HTTP.get('www.google.com', '/') # ===> "abc\n"
|
72
|
-
|
90
|
+
|
73
91
|
### Request with basic authentication
|
74
92
|
|
75
93
|
stub_request(:any, "john:smith@www.google.com")
|
76
94
|
|
77
95
|
Net::HTTP.get(URI.parse('http://john:smith@www.google.com')) # ===> Success
|
78
|
-
|
79
|
-
### Matching
|
96
|
+
|
97
|
+
### Matching uris using regular expressions
|
80
98
|
|
81
99
|
stub_request(:any, /.*google.*/)
|
82
100
|
|
@@ -96,29 +114,23 @@ Now you are ready to write your tests/specs with stubbed HTTP calls.
|
|
96
114
|
|
97
115
|
Net::HTTP.get('www.something.com', '/') # ===> Failure
|
98
116
|
|
99
|
-
### Clearing stubs
|
100
|
-
|
101
|
-
stub_request(:any, "www.google.com")
|
102
|
-
|
103
|
-
Net::HTTP.get('www.google.com', '/') # ===> Success
|
104
|
-
|
105
|
-
reset_webmock
|
106
|
-
|
107
|
-
Net::HTTP.get('www.google.com', '/') # ===> Failure
|
108
117
|
|
118
|
+
## Setting Expectations
|
109
119
|
|
110
|
-
###
|
120
|
+
### Setting expectations in Test::Unit
|
121
|
+
require 'webmock/test_unit'
|
111
122
|
|
112
123
|
stub_request(:any, "www.google.com")
|
113
124
|
|
114
|
-
|
115
|
-
req = Net::HTTP::Post.new(
|
125
|
+
uri = URI.parse('http://www.google.com/')
|
126
|
+
req = Net::HTTP::Post.new(uri.path)
|
116
127
|
req['Content-Length'] = 3
|
117
|
-
res = Net::HTTP.start(
|
128
|
+
res = Net::HTTP.start(uri.host, uri.port) {|http|
|
118
129
|
http.request(req, 'abc')
|
119
130
|
}
|
120
131
|
|
121
|
-
assert_requested :post, "http://www.google.com",
|
132
|
+
assert_requested :post, "http://www.google.com",
|
133
|
+
:headers => {'Content-Length' => 3}, :body => "abc", :times => 1 # ===> Success
|
122
134
|
|
123
135
|
assert_not_requested :get, "http://www.something.com" # ===> Success
|
124
136
|
|
@@ -130,68 +142,149 @@ Now you are ready to write your tests/specs with stubbed HTTP calls.
|
|
130
142
|
|
131
143
|
assert_requested :get, "http://www.google.com" # ===> Success
|
132
144
|
|
133
|
-
### RSpec matchers 1
|
134
145
|
|
135
|
-
|
136
|
-
|
137
|
-
request(:post, "www.something.com").should have_been_made.times(3)
|
138
|
-
|
139
|
-
request(:any, "www.example.com").should_not have_been_made
|
146
|
+
### Setting expectations in RSpec
|
147
|
+
This style is borrowed from [fakeweb-matcher](http://github.com/freelancing-god/fakeweb-matcher)
|
140
148
|
|
141
|
-
|
149
|
+
require 'webmock/rspec'
|
142
150
|
|
143
151
|
WebMock.should have_requested(:get, "www.google.com").with(:body => "abc", :headers => {'Content-Length' => 3}).twice
|
144
152
|
|
145
153
|
WebMock.should_not have_requested(:get, "www.something.com")
|
146
154
|
|
147
|
-
|
148
|
-
-----
|
155
|
+
### Different way of setting expectations in RSpec
|
149
156
|
|
150
|
-
|
157
|
+
request(:post, "www.google.com").with(:body => "abc", :headers => {'Content-Length' => 3}).should have_been_made.once
|
158
|
+
|
159
|
+
request(:post, "www.something.com").should have_been_made.times(3)
|
151
160
|
|
152
|
-
|
161
|
+
request(:any, "www.example.com").should_not have_been_made
|
153
162
|
|
154
|
-
* request url matches stubbed request url pattern
|
155
|
-
* and request method is the same as stubbed request method or stubbed request method is :any
|
156
|
-
* and request body is the same as stubbed request body or stubbed request body is not set (is nil)
|
157
|
-
* and request headers are the same as stubbed request headers or stubbed request headers are a subset of request headers or stubbed request headers are not set
|
158
163
|
|
159
|
-
|
164
|
+
## Clearing stubs and request history
|
160
165
|
|
161
|
-
|
162
|
-
|
166
|
+
If you want to reset all current stubs and history of requests use `WebMock.reset_webmock`
|
167
|
+
|
168
|
+
stub_request(:any, "www.google.com")
|
169
|
+
|
170
|
+
Net::HTTP.get('www.google.com', '/') # ===> Success
|
171
|
+
|
172
|
+
reset_webmock
|
173
|
+
|
174
|
+
Net::HTTP.get('www.google.com', '/') # ===> Failure
|
175
|
+
|
176
|
+
assert_not_requested :get, "www.google.com" # ===> Success
|
177
|
+
|
178
|
+
|
179
|
+
## Matching requests
|
180
|
+
|
181
|
+
An executed request matches stubbed request if it passes following criteria:
|
182
|
+
|
183
|
+
Request URI matches stubbed request URI string or Regexp pattern<br/>
|
184
|
+
And request method is the same as stubbed request method or stubbed request method is :any<br/>
|
185
|
+
And request body is the same as stubbed request body or stubbed request body is not set (is nil)<br/>
|
186
|
+
And request headers match stubbed request headers, or stubbed request headers match a subset of request headers, or stubbed request headers are not set
|
187
|
+
|
188
|
+
## Precedence of stubs
|
189
|
+
|
190
|
+
Always the last declared stub matching the request will be applied i.e:
|
163
191
|
|
164
192
|
stub_request(:get, "www.google.com").to_return(:body => "abc")
|
165
193
|
stub_request(:get, "www.google.com").to_return(:body => "def")
|
166
194
|
|
167
195
|
Net::HTTP.get('www.google.com', '/') # ====> "def"
|
168
196
|
|
169
|
-
|
170
|
-
|
197
|
+
## Matching URIs
|
198
|
+
|
199
|
+
WebMock will match all different representations of the same URI.
|
200
|
+
|
201
|
+
I.e all the following representations of the URI are equal:
|
202
|
+
|
203
|
+
"www.google.com"
|
204
|
+
"www.google.com/"
|
205
|
+
"www.google.com:80"
|
206
|
+
"www.google.com:80/"
|
207
|
+
"http://www.google.com"
|
208
|
+
"http://www.google.com/"
|
209
|
+
"http://www.google.com:80"
|
210
|
+
"http://www.google.com:80/"
|
211
|
+
|
212
|
+
The following URIs with basic authentication are also equal for WebMock
|
213
|
+
|
214
|
+
"a b:pass@www.google.com"
|
215
|
+
"a b:pass@www.google.com/"
|
216
|
+
"a b:pass@www.google.com:80"
|
217
|
+
"a b:pass@www.google.com:80/"
|
218
|
+
"http://a b:pass@www.google.com"
|
219
|
+
"http://a b:pass@www.google.com/"
|
220
|
+
"http://a b:pass@www.google.com:80"
|
221
|
+
"http://a b:pass@www.google.com:80/"
|
222
|
+
"a%20b:pass@www.google.com"
|
223
|
+
"a%20b:pass@www.google.com/"
|
224
|
+
"a%20b:pass@www.google.com:80"
|
225
|
+
"a%20b:pass@www.google.com:80/"
|
226
|
+
"http://a%20b:pass@www.google.com"
|
227
|
+
"http://a%20b:pass@www.google.com/"
|
228
|
+
"http://a%20b:pass@www.google.com:80"
|
229
|
+
"http://a%20b:pass@www.google.com:80/"
|
230
|
+
|
231
|
+
or these
|
232
|
+
|
233
|
+
"www.google.com/big image.jpg/?a=big image&b=c"
|
234
|
+
"www.google.com/big%20image.jpg/?a=big%20image&b=c"
|
235
|
+
"www.google.com:80/big image.jpg/?a=big image&b=c"
|
236
|
+
"www.google.com:80/big%20image.jpg/?a=big%20image&b=c"
|
237
|
+
"http://www.google.com/big image.jpg/?a=big image&b=c"
|
238
|
+
"http://www.google.com/big%20image.jpg/?a=big%20image&b=c"
|
239
|
+
"http://www.google.com:80/big image.jpg/?a=big image&b=c"
|
240
|
+
"http://www.google.com:80/big%20image.jpg/?a=big%20image&b=c"
|
241
|
+
|
242
|
+
|
243
|
+
If you provide Regexp to match URI, WebMock will try to match it against every valid form of the same url.
|
244
|
+
|
245
|
+
I.e `/.*big image.*/` will match `www.google.com/big%20image.jpg` because it is equivalent of `www.google.com/big image.jpg`
|
246
|
+
|
247
|
+
|
248
|
+
## Matching headers
|
249
|
+
|
250
|
+
WebMock will match request headers against stubbed request headers in the following situations:
|
251
|
+
|
252
|
+
1. Stubbed request has headers specified and request headers are the same as stubbed headers <br/>
|
253
|
+
i.e stubbed headers: `{ 'Header1' => 'Value1', 'Header1' => 'Value1' }`, requested: `{ 'Header1' => 'Value1', 'Header1' => 'Value1' }`
|
254
|
+
|
255
|
+
2. Stubbed request has headers specified and stubbed request headers are a subset of request headers <br/>
|
256
|
+
i.e stubbed headers: `{ 'Header1' => 'Value1' }`, requested: `{ 'Header1' => 'Value1', 'Header1' => 'Value1' }`
|
257
|
+
|
258
|
+
3. Stubbed request has no headers <br/>
|
259
|
+
i.e stubbed headers: `nil`, requested: `{ 'Header1' => 'Value1', 'Header1' => 'Value1' }`
|
260
|
+
|
261
|
+
WebMock normalises headers and treats all forms of same headers as equal:
|
262
|
+
i.e the following two sets of headers are equal:
|
263
|
+
|
264
|
+
`{ "Header1" => "value1", :content_length => 123, :X_CuStOm_hEAder => :value }`
|
265
|
+
|
266
|
+
`{ :header1 => "value1", "Content-Length" => 123, "x-cuSTOM-HeAder" => "value" }`
|
267
|
+
|
268
|
+
|
269
|
+
## Bugs and Issues
|
171
270
|
|
172
271
|
Please submit them here [http://github.com/bblimke/webmock/issues](http://github.com/bblimke/webmock/issues)
|
173
272
|
|
174
|
-
Suggestions
|
175
|
-
------------
|
273
|
+
## Suggestions
|
176
274
|
|
177
275
|
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)
|
178
276
|
|
179
277
|
I'm particularly interested in how the DSL could be improved.
|
180
278
|
|
181
|
-
|
182
|
-
----
|
183
|
-
|
184
|
-
* Add EventMachine::Protocols::HttpClient adapter
|
279
|
+
## Credits
|
185
280
|
|
186
|
-
|
187
|
-
-------
|
281
|
+
Thanks to my fellow [Bambinos](http://new-bamboo.co.uk/) for all the great suggestions!
|
188
282
|
|
189
|
-
Thank you Fakeweb! This library
|
190
|
-
I took couple of solutions from that project. I also copied some code i.e Net:
|
283
|
+
Thank you Fakeweb! This library was inspired by [FakeWeb](fakeweb.rubyforge.org).
|
284
|
+
I took couple of solutions from that project. I also copied some code i.e Net:HTTP adapter.
|
191
285
|
Fakeweb architecture unfortunately didn't allow me to extend it easily with the features I needed.
|
192
286
|
I also preferred some things to work differently i.e request stub precedence.
|
193
287
|
|
194
|
-
Copyright
|
195
|
-
---------
|
288
|
+
## Copyright
|
196
289
|
|
197
290
|
Copyright 2009 Bartosz Blimke. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -10,6 +10,7 @@ begin
|
|
10
10
|
gem.email = "bartosz.blimke@gmail.com"
|
11
11
|
gem.homepage = "http://github.com/bblimke/webmock"
|
12
12
|
gem.authors = ["Bartosz Blimke"]
|
13
|
+
gem.add_dependency "addressable", ">= 2.1.1"
|
13
14
|
gem.add_development_dependency "rspec", ">= 1.2.9"
|
14
15
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
16
|
end
|
@@ -34,7 +35,7 @@ require 'rake/testtask'
|
|
34
35
|
Rake::TestTask.new(:test) do |test|
|
35
36
|
test.test_files = FileList["test/**/*.rb"].exclude("test/test_helper.rb")
|
36
37
|
test.verbose = false
|
37
|
-
test.warning =
|
38
|
+
test.warning = false
|
38
39
|
end
|
39
40
|
|
40
41
|
task :spec => :check_dependencies
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.7.
|
1
|
+
0.7.2
|
data/lib/webmock.rb
CHANGED
@@ -1,18 +1,21 @@
|
|
1
1
|
require 'singleton'
|
2
2
|
|
3
|
+
require 'addressable/uri'
|
4
|
+
|
3
5
|
require 'webmock/http_lib_adapters/net_http'
|
4
6
|
|
5
7
|
require 'webmock/errors'
|
8
|
+
|
9
|
+
require 'webmock/util/uri'
|
10
|
+
require 'webmock/util/headers'
|
11
|
+
require 'webmock/util/hash_counter'
|
12
|
+
|
6
13
|
require 'webmock/request_profile'
|
7
|
-
require 'webmock/
|
8
|
-
require 'webmock/url'
|
14
|
+
require 'webmock/request_signature'
|
9
15
|
require 'webmock/request_stub'
|
10
|
-
require 'webmock/utility'
|
11
|
-
require 'webmock/config'
|
12
16
|
require 'webmock/response'
|
13
|
-
require 'webmock/util/hash_counter'
|
14
|
-
require 'webmock/request_registry'
|
15
|
-
require 'webmock/webmock'
|
16
17
|
|
17
|
-
require 'webmock/
|
18
|
-
require 'webmock/
|
18
|
+
require 'webmock/request_execution_verifier'
|
19
|
+
require 'webmock/config'
|
20
|
+
require 'webmock/request_registry'
|
21
|
+
require 'webmock/webmock'
|
@@ -1,23 +1,21 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
14
|
-
}
|
15
|
-
|
16
|
-
module WebMock
|
17
|
-
private
|
18
|
-
def assertion_failure(message)
|
19
|
-
raise Spec::Expectations::ExpectationNotMetError.new(message)
|
20
|
-
end
|
1
|
+
require 'webmock'
|
2
|
+
require 'spec'
|
3
|
+
require 'webmock/adapters/rspec/request_profile_matcher'
|
4
|
+
require 'webmock/adapters/rspec/webmock_matcher'
|
5
|
+
require 'webmock/adapters/rspec/matchers'
|
6
|
+
|
7
|
+
Spec::Runner.configure { |config|
|
8
|
+
|
9
|
+
config.include WebMock::Matchers
|
10
|
+
|
11
|
+
config.before :each do
|
12
|
+
WebMock.reset_webmock
|
21
13
|
end
|
22
|
-
|
23
|
-
|
14
|
+
}
|
15
|
+
|
16
|
+
module WebMock
|
17
|
+
private
|
18
|
+
def assertion_failure(message)
|
19
|
+
raise Spec::Expectations::ExpectationNotMetError.new(message)
|
20
|
+
end
|
21
|
+
end
|