webmock 1.6.4 → 1.7.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/.gemtest +0 -0
- data/.gitignore +3 -1
- data/.travis.yml +6 -0
- data/CHANGELOG.md +211 -118
- data/Gemfile +16 -1
- data/Guardfile +24 -0
- data/LICENSE +1 -1
- data/README.md +64 -15
- data/Rakefile +19 -6
- data/lib/webmock.rb +9 -4
- data/lib/webmock/api.rb +5 -4
- data/lib/webmock/assertion_failure.rb +1 -1
- data/lib/webmock/callback_registry.rb +1 -1
- data/lib/webmock/config.rb +2 -2
- data/lib/webmock/cucumber.rb +1 -1
- data/lib/webmock/errors.rb +17 -5
- data/lib/webmock/http_lib_adapters/{curb.rb → curb_adapter.rb} +79 -49
- data/lib/webmock/http_lib_adapters/{em_http_request.rb → em_http_request/em_http_request_0_x.rb} +20 -15
- data/lib/webmock/http_lib_adapters/em_http_request/em_http_request_1_x.rb +201 -0
- data/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +11 -0
- data/lib/webmock/http_lib_adapters/http_lib_adapter.rb +7 -0
- data/lib/webmock/http_lib_adapters/http_lib_adapter_registry.rb +19 -0
- data/lib/webmock/http_lib_adapters/{httpclient.rb → httpclient_adapter.rb} +35 -8
- data/lib/webmock/http_lib_adapters/net_http.rb +84 -25
- data/lib/webmock/http_lib_adapters/net_http_response.rb +17 -17
- data/lib/webmock/http_lib_adapters/patron_adapter.rb +124 -0
- data/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb +166 -0
- data/lib/webmock/minitest.rb +15 -0
- data/lib/webmock/rack_response.rb +52 -0
- data/lib/webmock/request_pattern.rb +4 -2
- data/lib/webmock/request_signature.rb +4 -0
- data/lib/webmock/request_stub.rb +35 -2
- data/lib/webmock/responses_sequence.rb +2 -2
- data/lib/webmock/rspec.rb +2 -2
- data/lib/webmock/rspec/matchers.rb +9 -4
- data/lib/webmock/rspec/matchers/webmock_matcher.rb +1 -1
- data/lib/webmock/stub_registry.rb +1 -1
- data/lib/webmock/stub_request_snippet.rb +14 -11
- data/lib/webmock/util/hash_keys_stringifier.rb +4 -4
- data/lib/webmock/util/headers.rb +3 -3
- data/lib/webmock/util/json.rb +54 -0
- data/lib/webmock/util/uri.rb +1 -1
- data/lib/webmock/version.rb +1 -1
- data/lib/webmock/webmock.rb +20 -3
- data/minitest/test_helper.rb +29 -0
- data/minitest/test_webmock.rb +6 -0
- data/minitest/webmock_spec.rb +30 -0
- data/spec/curb_spec.rb +26 -8
- data/spec/curb_spec_helper.rb +6 -6
- data/spec/em_http_request_spec.rb +95 -1
- data/spec/em_http_request_spec_helper.rb +16 -16
- data/spec/errors_spec.rb +19 -4
- data/spec/example_curl_output.txt +22 -22
- data/spec/http_lib_adapters/http_lib_adapter_registry_spec.rb +17 -0
- data/spec/http_lib_adapters/http_lib_adapter_spec.rb +12 -0
- data/spec/httpclient_spec.rb +1 -1
- data/spec/httpclient_spec_helper.rb +3 -38
- data/spec/my_rack_app.rb +18 -0
- data/spec/net_http_shared.rb +125 -0
- data/spec/net_http_spec.rb +27 -31
- data/spec/net_http_spec_helper.rb +4 -34
- data/spec/network_connection.rb +1 -1
- data/spec/patron_spec_helper.rb +4 -7
- data/spec/quality_spec.rb +60 -0
- data/spec/rack_response_spec.rb +33 -0
- data/spec/real_net_http_spec.rb +20 -0
- data/spec/request_execution_verifier_spec.rb +8 -8
- data/spec/request_pattern_spec.rb +3 -3
- data/spec/request_stub_spec.rb +19 -19
- data/spec/response_spec.rb +8 -8
- data/spec/spec_helper.rb +14 -11
- data/spec/stub_request_snippet_spec.rb +85 -37
- data/spec/support/webmock_server.rb +62 -0
- data/spec/typhoeus_hydra_spec.rb +53 -0
- data/spec/typhoeus_hydra_spec_helper.rb +50 -0
- data/spec/util/headers_spec.rb +5 -5
- data/spec/util/json_spec.rb +7 -0
- data/spec/util/uri_spec.rb +1 -1
- data/spec/vendor/addressable/lib/uri.rb +1 -0
- data/spec/vendor/crack/lib/crack.rb +1 -0
- data/spec/vendor/right_http_connection-1.2.4/History.txt +4 -4
- data/spec/vendor/right_http_connection-1.2.4/README.txt +4 -4
- data/spec/vendor/right_http_connection-1.2.4/Rakefile +3 -3
- data/spec/vendor/right_http_connection-1.2.4/lib/net_fix.rb +4 -4
- data/spec/vendor/right_http_connection-1.2.4/setup.rb +4 -4
- data/spec/webmock_shared.rb +375 -143
- data/spec/webmock_spec.rb +7 -0
- data/test/http_request.rb +24 -0
- data/test/shared_test.rb +47 -0
- data/test/test_helper.rb +6 -3
- data/test/test_webmock.rb +2 -67
- data/webmock.gemspec +8 -7
- metadata +153 -88
- data/lib/webmock/http_lib_adapters/patron.rb +0 -100
- data/spec/other_net_http_libs_spec.rb +0 -30
data/spec/curb_spec_helper.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require 'ostruct'
|
|
2
|
+
|
|
1
3
|
module CurbSpecHelper
|
|
2
4
|
def http_request(method, uri, options = {}, &block)
|
|
3
5
|
uri = Addressable::URI.heuristic_parse(uri)
|
|
@@ -5,7 +7,8 @@ module CurbSpecHelper
|
|
|
5
7
|
|
|
6
8
|
curl = curb_http_request(uri, method, body, options)
|
|
7
9
|
|
|
8
|
-
status, response_headers =
|
|
10
|
+
status, response_headers =
|
|
11
|
+
WebMock::HttpLibAdapters::CurbAdapter.parse_header_string(curl.header_str)
|
|
9
12
|
|
|
10
13
|
OpenStruct.new(
|
|
11
14
|
:body => curl.body_str,
|
|
@@ -17,7 +20,7 @@ module CurbSpecHelper
|
|
|
17
20
|
|
|
18
21
|
def setup_request(uri, curl, options={})
|
|
19
22
|
curl ||= Curl::Easy.new
|
|
20
|
-
curl.url = uri.omit(:userinfo).to_s
|
|
23
|
+
curl.url = uri.omit(:userinfo).to_s
|
|
21
24
|
curl.username = uri.user
|
|
22
25
|
curl.password = uri.password
|
|
23
26
|
curl.timeout = 10
|
|
@@ -38,9 +41,6 @@ module CurbSpecHelper
|
|
|
38
41
|
Curl::Err::ConnectionFailedError
|
|
39
42
|
end
|
|
40
43
|
|
|
41
|
-
def setup_expectations_for_real_request(options = {})
|
|
42
|
-
end
|
|
43
|
-
|
|
44
44
|
def http_library
|
|
45
45
|
:curb
|
|
46
46
|
end
|
|
@@ -54,7 +54,7 @@ module CurbSpecHelper
|
|
|
54
54
|
curl.post_body = body
|
|
55
55
|
when :put
|
|
56
56
|
curl.put_data = body
|
|
57
|
-
end
|
|
57
|
+
end
|
|
58
58
|
|
|
59
59
|
curl.http(method)
|
|
60
60
|
curl
|
|
@@ -10,6 +10,97 @@ unless RUBY_PLATFORM =~ /java/
|
|
|
10
10
|
|
|
11
11
|
it_should_behave_like "WebMock"
|
|
12
12
|
|
|
13
|
+
#functionality only supported for em-http-request 1.x
|
|
14
|
+
if defined?(EventMachine::HttpConnection)
|
|
15
|
+
describe "with middleware" do
|
|
16
|
+
|
|
17
|
+
it "should work with request middleware" do
|
|
18
|
+
stub_http_request(:get, "www.example.com").with(:body => 'bar')
|
|
19
|
+
|
|
20
|
+
middleware = Class.new do
|
|
21
|
+
def request(client, head, body)
|
|
22
|
+
[{}, 'bar']
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
EM.run do
|
|
27
|
+
conn = EventMachine::HttpRequest.new('http://www.example.com/')
|
|
28
|
+
|
|
29
|
+
conn.use middleware
|
|
30
|
+
|
|
31
|
+
http = conn.get(:body => 'foo')
|
|
32
|
+
|
|
33
|
+
http.callback do
|
|
34
|
+
WebMock.should have_requested(:get, "www.example.com").with(:body => 'bar')
|
|
35
|
+
EM.stop
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "should work with response middleware" do
|
|
41
|
+
stub_http_request(:get, "www.example.com").to_return(:body => 'foo')
|
|
42
|
+
|
|
43
|
+
middleware = Class.new do
|
|
44
|
+
def response(resp)
|
|
45
|
+
resp.response = 'bar'
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
EM.run do
|
|
50
|
+
conn = EventMachine::HttpRequest.new('http://www.example.com/')
|
|
51
|
+
|
|
52
|
+
conn.use middleware
|
|
53
|
+
|
|
54
|
+
http = conn.get
|
|
55
|
+
|
|
56
|
+
http.callback do
|
|
57
|
+
http.response.should be == 'bar'
|
|
58
|
+
EM.stop
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# not pretty, but it works
|
|
65
|
+
describe "with synchrony" do
|
|
66
|
+
let(:webmock_em_http) { File.expand_path(File.join(File.dirname(__FILE__), "../lib/webmock/http_lib_adapters/em_http_request/em_http_request_1_x.rb")) }
|
|
67
|
+
|
|
68
|
+
before(:each) do
|
|
69
|
+
# need to reload the webmock em-http adapter after we require synchrony
|
|
70
|
+
WebMock::HttpLibAdapters::EmHttpRequestAdapter.disable!
|
|
71
|
+
$".delete webmock_em_http
|
|
72
|
+
$".delete File.expand_path(File.join(File.dirname(__FILE__), "../lib/webmock/http_lib_adapters/em_http_request_adapter.rb"))
|
|
73
|
+
require 'em-synchrony'
|
|
74
|
+
require 'em-synchrony/em-http'
|
|
75
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "../lib/webmock/http_lib_adapters/em_http_request_adapter.rb"))
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "should work" do
|
|
79
|
+
stub_request(:post, /.*.testserver.com*/).to_return(:status => 200, :body => 'ok')
|
|
80
|
+
lambda {
|
|
81
|
+
EM.run do
|
|
82
|
+
fiber = Fiber.new do
|
|
83
|
+
http = EM::HttpRequest.new("http://www.testserver.com").post :body => "foo=bar&baz=bang", :timeout => 60
|
|
84
|
+
EM.stop
|
|
85
|
+
end
|
|
86
|
+
fiber.resume
|
|
87
|
+
end
|
|
88
|
+
}.should_not raise_error
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
after(:each) do
|
|
92
|
+
EM.send(:remove_const, :Synchrony)
|
|
93
|
+
EM.send(:remove_const, :HTTPMethods)
|
|
94
|
+
WebMock::HttpLibAdapters::EmHttpRequestAdapter.disable!
|
|
95
|
+
$".reject! {|path| path.include? "em-http-request"}
|
|
96
|
+
$".delete webmock_em_http
|
|
97
|
+
$".delete File.expand_path(File.join(File.dirname(__FILE__), "../lib/webmock/http_lib_adapters/em_http_request_adapter.rb"))
|
|
98
|
+
require 'em-http-request'
|
|
99
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "../lib/webmock/http_lib_adapters/em_http_request_adapter.rb"))
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
13
104
|
it "should work with streaming" do
|
|
14
105
|
stub_http_request(:get, "www.example.com").to_return(:body => "abc")
|
|
15
106
|
response = ""
|
|
@@ -36,7 +127,10 @@ unless RUBY_PLATFORM =~ /java/
|
|
|
36
127
|
end
|
|
37
128
|
|
|
38
129
|
describe "mocking EM::HttpClient API" do
|
|
39
|
-
before
|
|
130
|
+
before do
|
|
131
|
+
stub_http_request(:get, "www.example.com/")
|
|
132
|
+
WebMock::HttpLibAdapters::EmHttpRequestAdapter.enable!
|
|
133
|
+
end
|
|
40
134
|
subject do
|
|
41
135
|
client = nil
|
|
42
136
|
EM.run do
|
|
@@ -6,34 +6,37 @@ module EMHttpRequestSpecHelper
|
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
def http_request(method, uri, options = {}, &block)
|
|
9
|
+
@http = nil
|
|
10
|
+
head = options[:headers] || {}
|
|
9
11
|
response = nil
|
|
10
12
|
error = nil
|
|
11
13
|
uri = Addressable::URI.heuristic_parse(uri)
|
|
12
14
|
EventMachine.run {
|
|
13
|
-
request = EventMachine::HttpRequest.new("#{uri.
|
|
14
|
-
http = request.send(
|
|
15
|
-
:timeout => 10,
|
|
15
|
+
request = EventMachine::HttpRequest.new("#{uri.normalize.to_s}")
|
|
16
|
+
http = request.send(method, {
|
|
17
|
+
:timeout => 10,
|
|
16
18
|
:body => options[:body],
|
|
17
19
|
:query => options[:query],
|
|
18
|
-
'authorization' => [uri.user, uri.password]
|
|
19
|
-
|
|
20
|
+
:head => head.merge('authorization' => [uri.user, uri.password])
|
|
21
|
+
}, &block)
|
|
20
22
|
http.errback {
|
|
21
23
|
error = if http.respond_to?(:errors)
|
|
22
|
-
http.errors
|
|
24
|
+
http.errors
|
|
23
25
|
else
|
|
24
26
|
http.error
|
|
25
|
-
end
|
|
26
|
-
failed
|
|
27
|
+
end
|
|
28
|
+
failed
|
|
27
29
|
}
|
|
28
|
-
http.callback {
|
|
30
|
+
http.callback {
|
|
29
31
|
response = OpenStruct.new({
|
|
30
32
|
:body => http.response,
|
|
31
|
-
:headers => WebMock::Util::Headers.normalize_headers(extract_response_headers(http)),
|
|
33
|
+
:headers => WebMock::Util::Headers.normalize_headers(extract_response_headers(http)),
|
|
32
34
|
:message => http.response_header.http_reason,
|
|
33
35
|
:status => http.response_header.status.to_s
|
|
34
36
|
})
|
|
35
37
|
EventMachine.stop
|
|
36
38
|
}
|
|
39
|
+
@http = http
|
|
37
40
|
}
|
|
38
41
|
raise error if error
|
|
39
42
|
response
|
|
@@ -47,21 +50,18 @@ module EMHttpRequestSpecHelper
|
|
|
47
50
|
""
|
|
48
51
|
end
|
|
49
52
|
|
|
50
|
-
def setup_expectations_for_real_request(options = {})
|
|
51
|
-
end
|
|
52
|
-
|
|
53
53
|
def http_library
|
|
54
54
|
:em_http_request
|
|
55
55
|
end
|
|
56
|
-
|
|
56
|
+
|
|
57
57
|
private
|
|
58
|
-
|
|
58
|
+
|
|
59
59
|
def extract_response_headers(http)
|
|
60
60
|
headers = {}
|
|
61
61
|
if http.response_header
|
|
62
62
|
http.response_header.each do |k,v|
|
|
63
63
|
v = v.join(", ") if v.is_a?(Array)
|
|
64
|
-
headers[k] = v
|
|
64
|
+
headers[k] = v
|
|
65
65
|
end
|
|
66
66
|
end
|
|
67
67
|
headers
|
data/spec/errors_spec.rb
CHANGED
|
@@ -5,13 +5,28 @@ describe "errors" do
|
|
|
5
5
|
describe "message" do
|
|
6
6
|
it "should have message with request signature and snippet" do
|
|
7
7
|
request_signature = mock(:to_s => "aaa")
|
|
8
|
+
request_stub = mock
|
|
9
|
+
WebMock::RequestStub.stub!(:from_request_signature).and_return(request_stub)
|
|
8
10
|
WebMock::StubRequestSnippet.stub!(:new).
|
|
9
|
-
with(
|
|
11
|
+
with(request_stub).and_return(mock(:to_s => "bbb"))
|
|
10
12
|
expected = "Real HTTP connections are disabled. Unregistered request: aaa" +
|
|
11
13
|
"\n\nYou can stub this request with the following snippet:\n\n" +
|
|
12
|
-
"bbb\n\n============================================================"
|
|
13
|
-
WebMock::NetConnectNotAllowedError.new(request_signature).message.should == expected
|
|
14
|
+
"bbb\n\n============================================================"
|
|
15
|
+
WebMock::NetConnectNotAllowedError.new(request_signature).message.should == expected
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "should have message with registered stubs if available" do
|
|
19
|
+
request_signature = mock(:to_s => "aaa")
|
|
20
|
+
request_stub = mock
|
|
21
|
+
WebMock::StubRegistry.instance.stub!(:request_stubs).and_return([request_stub])
|
|
22
|
+
WebMock::RequestStub.stub!(:from_request_signature).and_return(request_stub)
|
|
23
|
+
WebMock::StubRequestSnippet.stub!(:new).
|
|
24
|
+
with(request_stub).and_return(mock(:to_s => "bbb"))
|
|
25
|
+
expected = "Real HTTP connections are disabled. Unregistered request: aaa" +
|
|
26
|
+
"\n\nYou can stub this request with the following snippet:\n\n" +
|
|
27
|
+
"bbb\n\nregistered request stubs:\n\nbbb\n\n============================================================"
|
|
28
|
+
WebMock::NetConnectNotAllowedError.new(request_signature).message.should == expected
|
|
14
29
|
end
|
|
15
30
|
end
|
|
16
31
|
end
|
|
17
|
-
end
|
|
32
|
+
end
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
HTTP/1.1 202 OK
|
|
2
|
-
Content-Type: text/html; charset=UTF-8
|
|
3
|
-
Connection: Keep-Alive
|
|
4
|
-
Date: Sat, 23 Jan 2010 01:01:05 GMT
|
|
5
|
-
Content-Length:
|
|
6
|
-
Accept: image/jpeg
|
|
7
|
-
Accept: image/png
|
|
8
|
-
|
|
9
|
-
<HTML>
|
|
10
|
-
<HEAD>
|
|
11
|
-
<TITLE>Example Web Page</TITLE>
|
|
12
|
-
</HEAD>
|
|
13
|
-
<body>
|
|
14
|
-
<p>You have reached this web page by typing "example.com",
|
|
15
|
-
"example.net",
|
|
16
|
-
or "example.org" into your web browser.</p>
|
|
17
|
-
<p>These domain names are reserved for use in documentation and are not available
|
|
18
|
-
for registration. See <a href="http://www.rfc-editor.org/rfc/rfc2606.txt">RFC
|
|
19
|
-
2606</a>, Section 3.</p>
|
|
20
|
-
</BODY>
|
|
21
|
-
</HTML>
|
|
22
|
-
|
|
1
|
+
HTTP/1.1 202 OK
|
|
2
|
+
Content-Type: text/html; charset=UTF-8
|
|
3
|
+
Connection: Keep-Alive
|
|
4
|
+
Date: Sat, 23 Jan 2010 01:01:05 GMT
|
|
5
|
+
Content-Length: 419
|
|
6
|
+
Accept: image/jpeg
|
|
7
|
+
Accept: image/png
|
|
8
|
+
|
|
9
|
+
<HTML>
|
|
10
|
+
<HEAD>
|
|
11
|
+
<TITLE>Example Web Page</TITLE>
|
|
12
|
+
</HEAD>
|
|
13
|
+
<body>
|
|
14
|
+
<p>You have reached this web page by typing "example.com",
|
|
15
|
+
"example.net",
|
|
16
|
+
or "example.org" into your web browser.</p>
|
|
17
|
+
<p>These domain names are reserved for use in documentation and are not available
|
|
18
|
+
for registration. See <a href="http://www.rfc-editor.org/rfc/rfc2606.txt">RFC
|
|
19
|
+
2606</a>, Section 3.</p>
|
|
20
|
+
</BODY>
|
|
21
|
+
</HTML>
|
|
22
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe WebMock::HttpLibAdapterRegistry do
|
|
4
|
+
describe "each_adapter" do
|
|
5
|
+
it "should yield block over each adapter" do
|
|
6
|
+
class MyAdapter < WebMock::HttpLibAdapter; end
|
|
7
|
+
WebMock::HttpLibAdapterRegistry.instance.register(:my_lib, MyAdapter)
|
|
8
|
+
adapters = []
|
|
9
|
+
WebMock::HttpLibAdapterRegistry.instance.each_adapter {|n,a|
|
|
10
|
+
adapters << [n, a]
|
|
11
|
+
}
|
|
12
|
+
adapters.should include([:my_lib, MyAdapter])
|
|
13
|
+
WebMock::HttpLibAdapterRegistry.instance.
|
|
14
|
+
http_lib_adapters.delete(:my_lib)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe WebMock::HttpLibAdapter do
|
|
4
|
+
describe "adapter_for" do
|
|
5
|
+
it "should add adapter to adapter registry" do
|
|
6
|
+
class MyAdapter < WebMock::HttpLibAdapter; end
|
|
7
|
+
WebMock::HttpLibAdapterRegistry.instance.
|
|
8
|
+
should_receive(:register).with(:my_lib, MyAdapter)
|
|
9
|
+
MyAdapter.adapter_for(:my_lib)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
data/spec/httpclient_spec.rb
CHANGED
|
@@ -2,7 +2,7 @@ module HTTPClientSpecHelper
|
|
|
2
2
|
class << self
|
|
3
3
|
attr_accessor :async_mode
|
|
4
4
|
end
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
def http_request(method, uri, options = {}, &block)
|
|
7
7
|
uri = Addressable::URI.heuristic_parse(uri)
|
|
8
8
|
c = HTTPClient.new
|
|
@@ -17,7 +17,7 @@ module HTTPClientSpecHelper
|
|
|
17
17
|
else
|
|
18
18
|
response = c.request(*params, &block)
|
|
19
19
|
end
|
|
20
|
-
headers = response.header.all.inject({}) do |headers, header|
|
|
20
|
+
headers = response.header.all.inject({}) do |headers, header|
|
|
21
21
|
if !headers.has_key?(header[0])
|
|
22
22
|
headers[header[0]] = header[1]
|
|
23
23
|
else
|
|
@@ -41,43 +41,8 @@ module HTTPClientSpecHelper
|
|
|
41
41
|
Errno::ECONNREFUSED
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
def setup_expectations_for_real_request(options = {})
|
|
45
|
-
socket = mock("TCPSocket")
|
|
46
|
-
TCPSocket.should_receive(:new).
|
|
47
|
-
with(options[:host], options[:port]).at_least(:once).and_return(socket)
|
|
48
|
-
|
|
49
|
-
socket.stub!(:closed?).and_return(false)
|
|
50
|
-
socket.stub!(:close).and_return(true)
|
|
51
|
-
|
|
52
|
-
request_parts = ["#{options[:method]} #{options[:path]} HTTP/1.1", "Host: #{options[:host]}"]
|
|
53
|
-
|
|
54
|
-
if options[:port] == 443
|
|
55
|
-
OpenSSL::SSL::SSLSocket.should_receive(:new).
|
|
56
|
-
with(socket, instance_of(OpenSSL::SSL::SSLContext)).
|
|
57
|
-
at_least(:once).and_return(socket = mock("SSLSocket"))
|
|
58
|
-
socket.should_receive(:connect).at_least(:once).with()
|
|
59
|
-
socket.should_receive(:peer_cert).and_return(mock('peer cert', :extensions => []))
|
|
60
|
-
socket.should_receive(:write).with(/#{request_parts[0]}.*#{request_parts[1]}.*/m).and_return(100)
|
|
61
|
-
else
|
|
62
|
-
socket.should_receive(:<<).with(/#{request_parts[0]}.*#{request_parts[1]}.*/m).and_return(100)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
socket.stub!(:sync=).with(true)
|
|
66
|
-
|
|
67
|
-
socket.should_receive(:gets).with("\n").
|
|
68
|
-
and_return("HTTP/1.1 #{options[:response_code]} #{options[:response_message]}\r\n",
|
|
69
|
-
"Content-Length: #{options[:response_body].length}\r\n",
|
|
70
|
-
"\r\n")
|
|
71
|
-
socket.stub(:readpartial) do |size, buf|
|
|
72
|
-
buf << options[:response_body]
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
socket.stub!(:eof?).and_return(true)
|
|
76
|
-
socket.stub!(:close).and_return(true)
|
|
77
|
-
end
|
|
78
|
-
|
|
79
44
|
def http_library
|
|
80
|
-
:
|
|
45
|
+
:httpclient
|
|
81
46
|
end
|
|
82
47
|
|
|
83
48
|
end
|
data/spec/my_rack_app.rb
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'rack'
|
|
2
|
+
|
|
3
|
+
class MyRackApp
|
|
4
|
+
def self.call(env)
|
|
5
|
+
case env.values_at('REQUEST_METHOD', 'PATH_INFO')
|
|
6
|
+
when ['GET', '/']
|
|
7
|
+
[200, {}, ["This is my root!"]]
|
|
8
|
+
when ['GET', '/greet']
|
|
9
|
+
name = env['QUERY_STRING'][/name=([^&]*)/, 1] || "World"
|
|
10
|
+
[200, {}, ["Hello, #{name}"]]
|
|
11
|
+
when ['POST', '/greet']
|
|
12
|
+
name = env["rack.input"].read[/name=([^&]*)/, 1] || "World"
|
|
13
|
+
[200, {}, ["Good to meet you, #{name}!"]]
|
|
14
|
+
else
|
|
15
|
+
[404, {}, ['']]
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
shared_examples_for "Net::HTTP" do
|
|
2
|
+
describe "when making real requests", :net_connect => true do
|
|
3
|
+
let(:port){ WebMockServer.instance.port }
|
|
4
|
+
|
|
5
|
+
before(:each) do
|
|
6
|
+
@http = Net::HTTP.new("localhost", port)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "should return a Net::ReadAdapter from response.body when a real request is made with a block and #read_body", :net_connect => true do
|
|
10
|
+
response = Net::HTTP.new("localhost", port).request_get('/') { |r| r.read_body { } }
|
|
11
|
+
response.body.should be_a(Net::ReadAdapter)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "should handle requests with block passed to read_body", :net_connect => true do
|
|
15
|
+
body = ""
|
|
16
|
+
req = Net::HTTP::Get.new("/")
|
|
17
|
+
Net::HTTP.start("localhost", port) do |http|
|
|
18
|
+
http.request(req) do |res|
|
|
19
|
+
res.read_body do |str|
|
|
20
|
+
body << str
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
body.should =~ /hello world/
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "should connect only once when connected on start", :net_connect => true do
|
|
28
|
+
@http = Net::HTTP.new('localhost', port)
|
|
29
|
+
socket_id_before_request = socket_id_after_request = nil
|
|
30
|
+
@http.start {|conn|
|
|
31
|
+
socket_id_before_request = conn.instance_variable_get(:@socket).object_id
|
|
32
|
+
conn.request(Net::HTTP::Get.new("/"))
|
|
33
|
+
socket_id_after_request = conn.instance_variable_get(:@socket).object_id
|
|
34
|
+
}
|
|
35
|
+
socket_id_after_request.should_not be_nil
|
|
36
|
+
socket_id_after_request.should == socket_id_before_request
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe "without start" do
|
|
40
|
+
it "should close connection after a real request" do
|
|
41
|
+
@http.get('/') { }
|
|
42
|
+
@http.should_not be_started
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "should execute block exactly once" do
|
|
46
|
+
times = 0
|
|
47
|
+
@http.get('/') { times += 1 }
|
|
48
|
+
times.should == 1
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "should have socket open during a real request" do
|
|
52
|
+
socket_id = nil
|
|
53
|
+
@http.get('/') {
|
|
54
|
+
socket_id = @http.instance_variable_get(:@socket).object_id
|
|
55
|
+
}
|
|
56
|
+
socket_id.should_not be_nil
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "should be started during a real request" do
|
|
60
|
+
started = nil
|
|
61
|
+
@http.get('/') {
|
|
62
|
+
started = @http.started?
|
|
63
|
+
}
|
|
64
|
+
started.should == true
|
|
65
|
+
@http.started?.should == false
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
describe "with start" do
|
|
70
|
+
it "should close connection after a real request" do
|
|
71
|
+
@http.start {|conn| conn.get('/') { } }
|
|
72
|
+
@http.should_not be_started
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "should execute block exactly once" do
|
|
76
|
+
times = 0
|
|
77
|
+
@http.start {|conn| conn.get('/') { times += 1 }}
|
|
78
|
+
times.should == 1
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it "should have socket open during a real request" do
|
|
82
|
+
socket_id = nil
|
|
83
|
+
@http.start {|conn| conn.get('/') {
|
|
84
|
+
socket_id = conn.instance_variable_get(:@socket).object_id
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
socket_id.should_not be_nil
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "should be started during a real request" do
|
|
91
|
+
started = nil
|
|
92
|
+
@http.start {|conn| conn.get('/') {
|
|
93
|
+
started = conn.started?
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
started.should == true
|
|
97
|
+
@http.started?.should == false
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
describe "with start without request block" do
|
|
102
|
+
it "should close connection after a real request" do
|
|
103
|
+
@http.start {|conn| conn.get('/') }
|
|
104
|
+
@http.should_not be_started
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it "should have socket open during a real request" do
|
|
108
|
+
socket_id = nil
|
|
109
|
+
@http.start {|conn|
|
|
110
|
+
socket_id = conn.instance_variable_get(:@socket).object_id
|
|
111
|
+
}
|
|
112
|
+
socket_id.should_not be_nil
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it "should be started during a real request" do
|
|
116
|
+
started = nil
|
|
117
|
+
@http.start {|conn|
|
|
118
|
+
started = conn.started?
|
|
119
|
+
}
|
|
120
|
+
started.should == true
|
|
121
|
+
@http.started?.should == false
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|