Skip to content

Commit

Permalink
Added support for declaring timeout errors using to_timeout
Browse files Browse the repository at this point in the history
  • Loading branch information
Bartosz Blimke committed Mar 14, 2010
1 parent 3314aad commit af52fe7
Show file tree
Hide file tree
Showing 12 changed files with 105 additions and 9 deletions.
16 changes: 14 additions & 2 deletions README.md
Expand Up @@ -127,7 +127,7 @@ You can also use WebMock without RSpec or Test::Unit support:

req = Net::HTTP::Get.new("/")
Net::HTTP.start("www.example.com") { |http| http.request(req) }.message # ===> "Internal Server Error"

### Replaying raw responses recorded with `curl -is`

`curl -is www.example.com > /tmp/example_curl_-is_output.txt`
Expand Down Expand Up @@ -162,6 +162,18 @@ You can also use WebMock without RSpec or Test::Unit support:

RestClient.post('www.example.net', 'abc') # ===> "abc\n"

### Raising errors

stub_request(:any, 'www.example.net').to_raise(StandardError)

RestClient.post('www.example.net', 'abc') # ===> StandardError

### Raising timeout errors

stub_request(:any, 'www.example.net').to_timeout

RestClient.post('www.example.net', 'abc') # ===> RestClient::RequestTimeout

### Multiple responses for repeated requests

stub_request(:get, "www.example.com").to_return({:body => "abc"}, {:body => "def"})
Expand All @@ -172,7 +184,7 @@ You can also use WebMock without RSpec or Test::Unit support:

Net::HTTP.get('www.example.com', '/') # ===> "def\n"

### Multiple responses using chained `to_return()` or `to_raise()` declarations
### Multiple responses using chained `to_return()`, `to_raise()` or `to_timeout` declarations

stub_request(:get, "www.example.com").
to_return({:body => "abc"}).then. #then() is just a syntactic sugar
Expand Down
1 change: 1 addition & 0 deletions lib/webmock/http_lib_adapters/httpclient.rb
Expand Up @@ -59,6 +59,7 @@ def build_httpclient_response(webmock_response, stream = false, &block)
response.reason=webmock_response.status[1]
webmock_response.headers.to_a.each { |name, value| response.header.set(name, value) }

raise HTTPClient::TimeoutError if webmock_response.should_timeout
webmock_response.raise_error_if_any

block.call(nil, body) if block
Expand Down
2 changes: 2 additions & 0 deletions lib/webmock/http_lib_adapters/net_http.rb
Expand Up @@ -122,6 +122,8 @@ def build_net_http_response(webmock_response, &block)

response.extend StubResponse

raise Timeout::Error if webmock_response.should_timeout

webmock_response.raise_error_if_any

yield response if block_given?
Expand Down
1 change: 1 addition & 0 deletions lib/webmock/http_lib_adapters/patron.rb
Expand Up @@ -66,6 +66,7 @@ def build_request_signature(req)
end

def build_patron_response(webmock_response)
raise Patron::TimeoutError if webmock_response.should_timeout
webmock_response.raise_error_if_any
res = Patron::Response.new
res.instance_variable_set(:@body, webmock_response.body)
Expand Down
5 changes: 5 additions & 0 deletions lib/webmock/request_stub.rb
Expand Up @@ -29,6 +29,11 @@ def to_raise(*exceptions)
})
self
end

def to_timeout
@responses_sequences << ResponsesSequence.new([ResponseFactory.response_for(:should_timeout => true)])
self
end

def response
if @responses_sequences.empty?
Expand Down
10 changes: 9 additions & 1 deletion lib/webmock/response.rb
Expand Up @@ -60,25 +60,33 @@ def raise_error_if_any
raise @exception.new('Exception from WebMock') if @exception
end

def should_timeout
@should_timeout == true
end

def options=(options)
self.headers = options[:headers]
self.status = options[:status]
self.body = options[:body]
@exception = options[:exception]
@should_timeout = options[:should_timeout]
end

def evaluate!(request_signature)
self.body = @body.call(request_signature) if @body.is_a?(Proc)
self.headers = @headers.call(request_signature) if @headers.is_a?(Proc)
self.status = @status.call(request_signature) if @status.is_a?(Proc)
@should_timeout = @should_timeout.call(request_signature) if @should_timeout.is_a?(Proc)
@exception = @exception.call(request_signature) if @exception.is_a?(Proc)
self
end

def ==(other)
self.body == other.body &&
self.headers === other.headers &&
self.status == other.status &&
self.exception == other.exception
self.exception == other.exception &&
self.should_timeout == other.should_timeout
end

private
Expand Down
4 changes: 4 additions & 0 deletions spec/httpclient_spec_helper.rb
Expand Up @@ -25,6 +25,10 @@ def http_request(method, uri, options = {}, &block)
})
end

def client_timeout_exception_class
HTTPClient::TimeoutError
end

def default_client_request_headers(request_method = nil, has_body = false)
{'Content-Type'=>'application/x-www-form-urlencoded'} if request_method == 'POST' && has_body
end
Expand Down
4 changes: 4 additions & 0 deletions spec/net_http_spec_helper.rb
Expand Up @@ -32,6 +32,10 @@ def default_client_request_headers(request_method = nil, has_body = false)
[k, v.flatten]
}.flatten]
end

def client_timeout_exception_class
Timeout::Error
end

# Sets several expectations that a real HTTP request makes it
# past WebMock to the socket layer. You can use this when you need to check
Expand Down
16 changes: 10 additions & 6 deletions spec/patron_spec_helper.rb
Expand Up @@ -3,30 +3,34 @@ def http_request(method, uri, options = {}, &block)
uri = Addressable::URI.heuristic_parse(uri)
sess = Patron::Session.new
sess.base_url = "#{uri.omit(:userinfo, :query).normalize.to_s}".gsub(/\/$/,"")

sess.username = uri.user
sess.password = uri.password

sess.timeout = 10

response = sess.request(method, "#{uri.path}#{uri.query ? '?' : ''}#{uri.query}", options[:headers] || {}, {
:data => options[:body]
})

OpenStruct.new({
:body => response.body,
:headers => WebMock::Util::Headers.normalize_headers(response.headers),
:status => response.status.to_s,
:message => response.status_line
})
end

def default_client_request_headers(request_method = nil, has_body = false)
nil
end

def client_timeout_exception_class
Patron::TimeoutError
end

def setup_expectations_for_real_request(options = {})
#TODO
end
end

end
22 changes: 22 additions & 0 deletions spec/request_stub_spec.rb
Expand Up @@ -124,6 +124,28 @@

end

describe "to_timeout" do

it "should assign response with timeout" do
@request_stub.to_timeout
@request_stub.response.should_timeout.should be_true
end

it "should assign sequence of responses with response with timeout" do
@request_stub.to_return(:body => "abc").then.to_timeout
@request_stub.response.body.should == "abc"
@request_stub.response.should_timeout.should be_true
end

it "should allow multiple timeouts to be declared" do
@request_stub.to_timeout.then.to_timeout.then.to_return(:body => "abc")
@request_stub.response.should_timeout.should be_true
@request_stub.response.should_timeout.should be_true
@request_stub.response.body.should == "abc"
end

end


describe "times" do

Expand Down
14 changes: 14 additions & 0 deletions spec/response_spec.rb
Expand Up @@ -64,6 +64,20 @@
end

end

describe "timeout" do

it "should know if it should timeout" do
@response = Response.new(:should_timeout => true)
@response.should_timeout.should be_true
end

it "should not timeout by default" do
@response = Response.new
@response.should_timeout.should be_false
end

end

describe "body" do

Expand Down
19 changes: 19 additions & 0 deletions spec/webmock_spec.rb
Expand Up @@ -291,6 +291,25 @@ class MyException < StandardError; end;
end


describe "raising timeout errors" do

it "should raise timeout exception if declared in a stubbed response" do
stub_http_request(:get, "www.example.com").to_timeout
lambda {
http_request(:get, "http://www.example.com/")
}.should raise_error(client_timeout_exception_class)
end

it "should raise exception if declared in a stubbed response after returning declared response" do
stub_http_request(:get, "www.example.com").to_return(:body => "abc").then.to_timeout
http_request(:get, "http://www.example.com/").body.should == "abc"
lambda {
http_request(:get, "http://www.example.com/")
}.should raise_error(client_timeout_exception_class)
end

end

describe "returning stubbed responses" do

it "should return declared body" do
Expand Down

0 comments on commit af52fe7

Please sign in to comment.