webmock 1.5.0 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +35 -0
- data/README.md +10 -24
- data/VERSION +1 -1
- data/lib/webmock.rb +4 -0
- data/lib/webmock/api.rb +1 -1
- data/lib/webmock/assertion_failure.rb +2 -4
- data/lib/webmock/cucumber.rb +8 -0
- data/lib/webmock/errors.rb +13 -1
- data/lib/webmock/http_lib_adapters/curb.rb +2 -2
- data/lib/webmock/http_lib_adapters/em_http_request.rb +31 -17
- data/lib/webmock/http_lib_adapters/httpclient.rb +3 -3
- data/lib/webmock/http_lib_adapters/net_http.rb +2 -2
- data/lib/webmock/http_lib_adapters/patron.rb +2 -2
- data/lib/webmock/request_execution_verifier.rb +18 -4
- data/lib/webmock/request_pattern.rb +1 -1
- data/lib/webmock/request_registry.rb +13 -28
- data/lib/webmock/request_signature.rb +15 -2
- data/lib/webmock/rspec.rb +32 -1
- data/lib/webmock/{adapters/rspec → rspec}/matchers.rb +4 -0
- data/lib/webmock/{adapters/rspec → rspec/matchers}/request_pattern_matcher.rb +0 -0
- data/lib/webmock/{adapters/rspec → rspec/matchers}/webmock_matcher.rb +0 -0
- data/lib/webmock/stub_registry.rb +43 -0
- data/lib/webmock/stub_request_snippet.rb +27 -0
- data/lib/webmock/test_unit.rb +20 -1
- data/lib/webmock/util/hash_counter.rb +9 -4
- data/lib/webmock/util/hash_keys_stringifier.rb +23 -0
- data/lib/webmock/webmock.rb +14 -4
- data/spec/curb_spec.rb +1 -1
- data/spec/curb_spec_helper.rb +0 -4
- data/spec/em_http_request_spec.rb +5 -0
- data/spec/em_http_request_spec_helper.rb +0 -4
- data/spec/errors_spec.rb +17 -0
- data/spec/httpclient_spec_helper.rb +0 -4
- data/spec/net_http_spec_helper.rb +2 -8
- data/spec/patron_spec_helper.rb +4 -11
- data/spec/request_execution_verifier_spec.rb +14 -4
- data/spec/request_registry_spec.rb +29 -80
- data/spec/request_signature_spec.rb +77 -3
- data/spec/spec_helper.rb +0 -18
- data/spec/stub_registry_spec.rb +86 -0
- data/spec/stub_request_snippet_spec.rb +47 -0
- data/spec/util/hash_counter_spec.rb +15 -0
- data/spec/util/hash_keys_stringifier_spec.rb +27 -0
- data/spec/webmock_shared.rb +63 -66
- data/test/test_helper.rb +5 -1
- data/test/test_webmock.rb +5 -2
- data/webmock.gemspec +17 -7
- metadata +19 -9
- data/lib/webmock/adapters/rspec.rb +0 -33
- data/lib/webmock/adapters/test_unit.rb +0 -19
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,40 @@
|
|
1
1
|
#Changelog
|
2
2
|
|
3
|
+
## 1.6.0
|
4
|
+
|
5
|
+
* Simplified integration with Test::Unit, RSpec and Cucumber. Now only a single file has to be required i.e.
|
6
|
+
|
7
|
+
require 'webmock/test_unit'
|
8
|
+
require 'webmock/rspec'
|
9
|
+
require 'webmock/cucumber'
|
10
|
+
|
11
|
+
* The error message on unstubbed request now contains code snippet which can be used to stub this request. Thanks to Martyn Loughran for suggesting this feature.
|
12
|
+
|
13
|
+
* The expectation failure message now contains a list of made requests. Thanks to Martyn Loughran for suggesting this feature.
|
14
|
+
|
15
|
+
* Added `WebMock.print_executed_requests` method which can be useful to find out what requests were made until a given point.
|
16
|
+
|
17
|
+
* em-http-request adapter is now activated by replacing EventMachine::HttpRequest constant, instead of monkeypatching the original class.
|
18
|
+
|
19
|
+
This technique is borrowed from em-http-request native mocking module. It allows switching WebMock adapter on an off, and using it interchangeably with em-http-request native mocking i.e:
|
20
|
+
|
21
|
+
EventMachine::WebMockHttpRequest.activate!
|
22
|
+
EventMachine::WebMockHttpRequest.deactivate!
|
23
|
+
|
24
|
+
Thanks to Martyn Loughran for suggesting this feature.
|
25
|
+
|
26
|
+
* `WebMock.reset_webmock` is deprecated in favour of new `WebMock.reset!`
|
27
|
+
|
28
|
+
* Fixed integration with Cucumber. Previously documented example didn't work with new versions of Cucumber.
|
29
|
+
|
30
|
+
* Fixed stubbing requests with body declared as a hash. Thanks to Erik Michaels-Ober for reporting the issue.
|
31
|
+
|
32
|
+
* Fixed issue with em-http-request adapter which didn't work when :query option value was passed as a string, not a hash. Thanks to Chee Yeo for reporting the issue.
|
33
|
+
|
34
|
+
* Fixed problem with assert_requested which didn't work if used outside rspec or test/unit
|
35
|
+
|
36
|
+
* Removed dependency on json gem
|
37
|
+
|
3
38
|
## 1.5.0
|
4
39
|
|
5
40
|
* Support for dynamically evaluated raw responses recorded with `curl -is` <br/>
|
data/README.md
CHANGED
@@ -25,17 +25,19 @@ Supported HTTP libraries
|
|
25
25
|
|
26
26
|
##Installation
|
27
27
|
|
28
|
-
|
28
|
+
gem install webmock --source http://gemcutter.org
|
29
|
+
|
30
|
+
### or to install the latest development version from github master
|
31
|
+
|
32
|
+
git clone http://github.com/bblimke/webmock.git
|
33
|
+
cd webmock
|
34
|
+
rake install
|
29
35
|
|
30
36
|
### Test::Unit
|
31
37
|
|
32
38
|
Add the following code to `test/test_helper.rb`
|
33
39
|
|
34
40
|
require 'webmock/test_unit'
|
35
|
-
|
36
|
-
class Test::Unit::TestCase
|
37
|
-
include WebMock::API
|
38
|
-
end
|
39
41
|
|
40
42
|
### RSpec
|
41
43
|
|
@@ -43,32 +45,16 @@ Add the following code to `spec/spec_helper`:
|
|
43
45
|
|
44
46
|
require 'webmock/rspec'
|
45
47
|
|
46
|
-
Spec::Runner.configure do |config|
|
47
|
-
config.include WebMock::API
|
48
|
-
end
|
49
|
-
|
50
|
-
### RSpec 2
|
51
|
-
|
52
|
-
Add the following code to `spec/spec_helper`:
|
53
|
-
|
54
|
-
require 'webmock/rspec'
|
55
|
-
|
56
|
-
RSpec.configure do |config|
|
57
|
-
config.include WebMock::API
|
58
|
-
end
|
59
|
-
|
60
48
|
### Cucumber
|
61
49
|
|
62
50
|
Add the following code to `features/support/env.rb`
|
63
51
|
|
64
|
-
require 'webmock/
|
65
|
-
World(WebMock::API, WebMock::Matchers)
|
52
|
+
require 'webmock/cucumber'
|
66
53
|
|
67
54
|
You can also use WebMock outside a test framework:
|
68
55
|
|
69
56
|
require 'webmock'
|
70
57
|
include WebMock::API
|
71
|
-
include WebMock::Matchers
|
72
58
|
|
73
59
|
## Examples
|
74
60
|
|
@@ -392,13 +378,13 @@ This forces WebMock Net::HTTP adapter to always connect on `Net::HTTP.start`.
|
|
392
378
|
|
393
379
|
## Clearing stubs and request history
|
394
380
|
|
395
|
-
If you want to reset all current stubs and history of requests use `WebMock.
|
381
|
+
If you want to reset all current stubs and history of requests use `WebMock.reset!`
|
396
382
|
|
397
383
|
stub_request(:any, "www.example.com")
|
398
384
|
|
399
385
|
Net::HTTP.get('www.example.com', '/') # ===> Success
|
400
386
|
|
401
|
-
|
387
|
+
WebMock.reset!
|
402
388
|
|
403
389
|
Net::HTTP.get('www.example.com', '/') # ===> Failure
|
404
390
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.6.0
|
data/lib/webmock.rb
CHANGED
@@ -16,6 +16,7 @@ require 'webmock/errors'
|
|
16
16
|
require 'webmock/util/uri'
|
17
17
|
require 'webmock/util/headers'
|
18
18
|
require 'webmock/util/hash_counter'
|
19
|
+
require 'webmock/util/hash_keys_stringifier'
|
19
20
|
|
20
21
|
require 'webmock/request_pattern'
|
21
22
|
require 'webmock/request_signature'
|
@@ -23,10 +24,13 @@ require 'webmock/responses_sequence'
|
|
23
24
|
require 'webmock/request_stub'
|
24
25
|
require 'webmock/response'
|
25
26
|
|
27
|
+
require 'webmock/stub_request_snippet'
|
28
|
+
|
26
29
|
require 'webmock/assertion_failure'
|
27
30
|
require 'webmock/request_execution_verifier'
|
28
31
|
require 'webmock/config'
|
29
32
|
require 'webmock/callback_registry'
|
30
33
|
require 'webmock/request_registry'
|
34
|
+
require 'webmock/stub_registry'
|
31
35
|
require 'webmock/api'
|
32
36
|
require 'webmock/webmock'
|
data/lib/webmock/api.rb
CHANGED
@@ -3,7 +3,7 @@ module WebMock
|
|
3
3
|
extend self
|
4
4
|
|
5
5
|
def stub_request(method, uri)
|
6
|
-
WebMock::
|
6
|
+
WebMock::StubRegistry.instance.register_request_stub(WebMock::RequestStub.new(method, uri))
|
7
7
|
end
|
8
8
|
|
9
9
|
alias_method :stub_http_request, :stub_request
|
@@ -1,13 +1,11 @@
|
|
1
1
|
module WebMock
|
2
2
|
class AssertionFailure
|
3
|
+
@error_class = RuntimeError
|
3
4
|
class << self
|
4
|
-
|
5
|
-
@error_class = RuntimeError
|
6
|
-
|
5
|
+
attr_accessor :error_class
|
7
6
|
def failure(message)
|
8
7
|
raise @error_class.new(message)
|
9
8
|
end
|
10
|
-
|
11
9
|
end
|
12
10
|
end
|
13
11
|
end
|
data/lib/webmock/errors.rb
CHANGED
@@ -2,7 +2,19 @@ module WebMock
|
|
2
2
|
|
3
3
|
class NetConnectNotAllowedError < StandardError
|
4
4
|
def initialize(request_signature)
|
5
|
-
|
5
|
+
text = "Real HTTP connections are disabled. Unregistered request: #{request_signature}"
|
6
|
+
text << stubbing_instructions(request_signature)
|
7
|
+
super(text)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def stubbing_instructions(request_signature)
|
13
|
+
text = "\n\n"
|
14
|
+
text << "You can stub this request with the following snippet:\n\n"
|
15
|
+
text << WebMock::StubRequestSnippet.new(request_signature).to_s
|
16
|
+
text << "\n\n" + "="*60
|
17
|
+
text
|
6
18
|
end
|
7
19
|
end
|
8
20
|
|
@@ -6,8 +6,8 @@ if defined?(Curl)
|
|
6
6
|
request_signature = build_request_signature
|
7
7
|
WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
|
8
8
|
|
9
|
-
if WebMock::
|
10
|
-
webmock_response = WebMock::
|
9
|
+
if WebMock::StubRegistry.instance.registered_request?(request_signature)
|
10
|
+
webmock_response = WebMock::StubRegistry.instance.response_for_request(request_signature)
|
11
11
|
build_curb_response(webmock_response)
|
12
12
|
WebMock::CallbackRegistry.invoke_callbacks(
|
13
13
|
{:lib => :curb}, request_signature, webmock_response)
|
@@ -1,9 +1,13 @@
|
|
1
1
|
if defined?(EventMachine::HttpRequest)
|
2
2
|
|
3
3
|
module EventMachine
|
4
|
-
|
4
|
+
OriginalHttpRequest = HttpRequest unless const_defined?(:OriginalHttpRequest)
|
5
5
|
|
6
|
-
|
6
|
+
class WebMockHttpRequest < EventMachine::HttpRequest
|
7
|
+
|
8
|
+
include HttpEncoding
|
9
|
+
|
10
|
+
class WebMockHttpClient < EventMachine::HttpClient
|
7
11
|
|
8
12
|
def setup(response, uri, error = nil)
|
9
13
|
@uri = uri
|
@@ -17,7 +21,7 @@ if defined?(EventMachine::HttpRequest)
|
|
17
21
|
end
|
18
22
|
end
|
19
23
|
end
|
20
|
-
|
24
|
+
|
21
25
|
def unbind
|
22
26
|
end
|
23
27
|
|
@@ -30,11 +34,11 @@ if defined?(EventMachine::HttpRequest)
|
|
30
34
|
|
31
35
|
WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
|
32
36
|
|
33
|
-
if WebMock::
|
34
|
-
webmock_response = WebMock::
|
37
|
+
if WebMock::StubRegistry.instance.registered_request?(request_signature)
|
38
|
+
webmock_response = WebMock::StubRegistry.instance.response_for_request(request_signature)
|
35
39
|
WebMock::CallbackRegistry.invoke_callbacks(
|
36
|
-
|
37
|
-
client =
|
40
|
+
{:lib => :em_http_request}, request_signature, webmock_response)
|
41
|
+
client = WebMockHttpClient.new(nil)
|
38
42
|
client.on_error("WebMock timeout error") if webmock_response.should_timeout
|
39
43
|
client.setup(make_raw_response(webmock_response), @uri,
|
40
44
|
webmock_response.should_timeout ? "WebMock timeout error" : nil)
|
@@ -54,13 +58,13 @@ if defined?(EventMachine::HttpRequest)
|
|
54
58
|
raise WebMock::NetConnectNotAllowedError.new(request_signature)
|
55
59
|
end
|
56
60
|
end
|
57
|
-
|
61
|
+
|
58
62
|
alias_method :send_request_without_webmock, :send_request
|
59
63
|
alias_method :send_request, :send_request_with_webmock
|
60
|
-
|
64
|
+
|
61
65
|
|
62
66
|
private
|
63
|
-
|
67
|
+
|
64
68
|
def build_webmock_response(http)
|
65
69
|
webmock_response = WebMock::Response.new
|
66
70
|
webmock_response.status = [http.response_header.status, http.response_header.http_reason]
|
@@ -78,7 +82,7 @@ if defined?(EventMachine::HttpRequest)
|
|
78
82
|
options = @options
|
79
83
|
method = @method
|
80
84
|
uri = @uri
|
81
|
-
end
|
85
|
+
end
|
82
86
|
|
83
87
|
if options[:authorization] || options['authorization']
|
84
88
|
auth = (options[:authorization] || options['authorization'])
|
@@ -87,9 +91,9 @@ if defined?(EventMachine::HttpRequest)
|
|
87
91
|
options.reject! {|k,v| k.to_s == 'authorization' } #we added it to url userinfo
|
88
92
|
uri.userinfo = userinfo
|
89
93
|
end
|
90
|
-
|
91
|
-
|
92
|
-
|
94
|
+
|
95
|
+
uri.query = encode_query(@req.uri, options[:query]).slice(/\?(.*)/, 1)
|
96
|
+
|
93
97
|
WebMock::RequestSignature.new(
|
94
98
|
method.downcase.to_sym,
|
95
99
|
uri.to_s,
|
@@ -99,11 +103,11 @@ if defined?(EventMachine::HttpRequest)
|
|
99
103
|
end
|
100
104
|
|
101
105
|
|
102
|
-
def make_raw_response(response)
|
106
|
+
def make_raw_response(response)
|
103
107
|
response.raise_error_if_any
|
104
|
-
|
108
|
+
|
105
109
|
status, headers, body = response.status, response.headers, response.body
|
106
|
-
|
110
|
+
|
107
111
|
response_string = []
|
108
112
|
response_string << "HTTP/1.1 #{status[0]} #{status[1]}"
|
109
113
|
|
@@ -116,8 +120,18 @@ if defined?(EventMachine::HttpRequest)
|
|
116
120
|
response_string.join("\n")
|
117
121
|
end
|
118
122
|
|
123
|
+
def self.activate!
|
124
|
+
EventMachine.send(:remove_const, :HttpRequest)
|
125
|
+
EventMachine.send(:const_set, :HttpRequest, WebMockHttpRequest)
|
126
|
+
end
|
119
127
|
|
128
|
+
def self.deactivate!
|
129
|
+
EventMachine.send(:remove_const, :HttpRequest)
|
130
|
+
EventMachine.send(:const_set, :HttpRequest, OriginalHttpRequest)
|
131
|
+
end
|
120
132
|
end
|
121
133
|
end
|
122
134
|
|
135
|
+
EventMachine::WebMockHttpRequest.activate!
|
136
|
+
|
123
137
|
end
|
@@ -15,8 +15,8 @@ if defined?(::HTTPClient)
|
|
15
15
|
|
16
16
|
WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
|
17
17
|
|
18
|
-
if WebMock::
|
19
|
-
webmock_response = WebMock::
|
18
|
+
if WebMock::StubRegistry.instance.registered_request?(request_signature)
|
19
|
+
webmock_response = WebMock::StubRegistry.instance.response_for_request(request_signature)
|
20
20
|
response = build_httpclient_response(webmock_response, stream, &block)
|
21
21
|
res = conn.push(response)
|
22
22
|
WebMock::CallbackRegistry.invoke_callbacks(
|
@@ -46,7 +46,7 @@ if defined?(::HTTPClient)
|
|
46
46
|
req = create_request(method, uri, query, body, extheader)
|
47
47
|
request_signature = build_request_signature(req)
|
48
48
|
|
49
|
-
if WebMock::
|
49
|
+
if WebMock::StubRegistry.instance.registered_request?(request_signature) ||
|
50
50
|
WebMock.net_connect_allowed?(request_signature.uri)
|
51
51
|
do_request_async_without_webmock(method, uri, query, body, extheader)
|
52
52
|
else
|
@@ -51,9 +51,9 @@ module Net #:nodoc: all
|
|
51
51
|
|
52
52
|
WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
|
53
53
|
|
54
|
-
if WebMock::
|
54
|
+
if WebMock::StubRegistry.instance.registered_request?(request_signature)
|
55
55
|
@socket = Net::HTTP.socket_type.new
|
56
|
-
webmock_response = WebMock::
|
56
|
+
webmock_response = WebMock::StubRegistry.instance.response_for_request(request_signature)
|
57
57
|
WebMock::CallbackRegistry.invoke_callbacks(
|
58
58
|
{:lib => :net_http}, request_signature, webmock_response)
|
59
59
|
build_net_http_response(webmock_response, &block)
|
@@ -8,8 +8,8 @@ if defined?(Patron)
|
|
8
8
|
|
9
9
|
WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
|
10
10
|
|
11
|
-
if WebMock::
|
12
|
-
webmock_response = WebMock::
|
11
|
+
if WebMock::StubRegistry.instance.registered_request?(request_signature)
|
12
|
+
webmock_response = WebMock::StubRegistry.instance.response_for_request(request_signature)
|
13
13
|
handle_file_name(req, webmock_response)
|
14
14
|
res = build_patron_response(webmock_response)
|
15
15
|
WebMock::CallbackRegistry.invoke_callbacks(
|
@@ -27,15 +27,29 @@ module WebMock
|
|
27
27
|
|
28
28
|
def failure_message
|
29
29
|
expected_times_executed = @expected_times_executed || 1
|
30
|
-
%Q(The request #{request_pattern.to_s} was expected to execute #{
|
30
|
+
text = %Q(The request #{request_pattern.to_s} was expected to execute #{times(expected_times_executed)} but it executed #{times(times_executed)})
|
31
|
+
text << self.class.executed_requests_message
|
32
|
+
text
|
31
33
|
end
|
32
34
|
|
33
35
|
def negative_failure_message
|
34
|
-
if @expected_times_executed
|
35
|
-
%Q(The request #{request_pattern.to_s} was not expected to execute #{
|
36
|
+
text = if @expected_times_executed
|
37
|
+
%Q(The request #{request_pattern.to_s} was not expected to execute #{times(expected_times_executed)} but it executed #{times(times_executed)})
|
36
38
|
else
|
37
|
-
%Q(The request #{request_pattern.to_s} was expected to execute 0 times but it executed #{
|
39
|
+
%Q(The request #{request_pattern.to_s} was expected to execute 0 times but it executed #{times(times_executed)})
|
38
40
|
end
|
41
|
+
text << self.class.executed_requests_message
|
42
|
+
text
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.executed_requests_message
|
46
|
+
"\n\nThe following requests were made:\n\n#{RequestRegistry.instance.to_s}\n" + "="*60
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def times(times)
|
52
|
+
"#{times} time#{ (times == 1) ? '' : 's'}"
|
39
53
|
end
|
40
54
|
|
41
55
|
end
|
@@ -3,47 +3,32 @@ module WebMock
|
|
3
3
|
class RequestRegistry
|
4
4
|
include Singleton
|
5
5
|
|
6
|
-
attr_accessor :
|
6
|
+
attr_accessor :requested_signatures
|
7
7
|
|
8
8
|
def initialize
|
9
|
-
|
9
|
+
reset!
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
13
|
-
self.request_stubs = []
|
12
|
+
def reset!
|
14
13
|
self.requested_signatures = Util::HashCounter.new
|
15
14
|
end
|
16
15
|
|
17
|
-
def register_request_stub(stub)
|
18
|
-
request_stubs.insert(0, stub)
|
19
|
-
stub
|
20
|
-
end
|
21
|
-
|
22
|
-
def registered_request?(request_signature)
|
23
|
-
request_stub_for(request_signature)
|
24
|
-
end
|
25
|
-
|
26
|
-
def response_for_request(request_signature)
|
27
|
-
stub = request_stub_for(request_signature)
|
28
|
-
stub ? evaluate_response_for_request(stub.response, request_signature) : nil
|
29
|
-
end
|
30
|
-
|
31
16
|
def times_executed(request_pattern)
|
32
17
|
self.requested_signatures.hash.select { |request_signature, times_executed|
|
33
18
|
request_pattern.matches?(request_signature)
|
34
19
|
}.inject(0) {|sum, (_, times_executed)| sum + times_executed }
|
35
20
|
end
|
36
21
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
22
|
+
def to_s
|
23
|
+
if requested_signatures.hash.empty?
|
24
|
+
"No requests were made."
|
25
|
+
else
|
26
|
+
text = ""
|
27
|
+
self.requested_signatures.each do |request_signature, times_executed|
|
28
|
+
text << "#{request_signature} was made #{times_executed} time#{times_executed == 1 ? '' : 's' }\n"
|
29
|
+
end
|
30
|
+
text
|
31
|
+
end
|
47
32
|
end
|
48
33
|
|
49
34
|
end
|