webmock 1.5.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|