Permalink
Browse files

Fix VCR::Net::HTTPResponse so it handles a nil body (such as for a HE…

…AD request).
  • Loading branch information...
1 parent 96c71dd commit a3d79c6ed2698aa5f4763c74b71a08e74f91d730 @myronmarston committed Sep 10, 2010
Showing with 72 additions and 65 deletions.
  1. +5 −3 lib/vcr/extensions/net_http_response.rb
  2. +67 −62 spec/extensions/net_http_response_spec.rb
@@ -17,9 +17,11 @@ def read_body(dest = nil, &block)
return @body if dest.nil? && block.nil?
raise ArgumentError.new("both arg and block given for HTTP method") if dest && block
- dest ||= ::Net::ReadAdapter.new(block)
- dest << @body
- @body = dest
+ if @body
+ dest ||= ::Net::ReadAdapter.new(block)
+ dest << @body
+ @body = dest
+ end
ensure
# allow subsequent calls to #read_body to proceed as normal, without our hack...
@__read_body_previously_called = true
@@ -1,85 +1,90 @@
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
-describe "Net::HTTP Response extensions" do
- context 'extending an already read response' do
- # WebMock uses this extension, too, and to prevent it from automatically being included
- # (and hence, causing issues with this spec), we remove all callbacks for the duration
- # of this spec, since the absence of any callbacks will prevent WebMock from reading the response
- # and extending the response with the response extension.
- before(:all) do
- @orig_webmock_callbacks = ::WebMock::CallbackRegistry.callbacks.dup
- ::WebMock::CallbackRegistry.reset
+describe VCR::Net::HTTPResponse do
+ # Disable the VCR/FakeWeb/WebMock Net::HTTP monkey patches so we don't have collisions with these specs
+ before(:all) { MonkeyPatches.disable! }
+ after(:all) { MonkeyPatches.enable! }
+
+ def self.it_allows_the_body_to_be_read(expected_regex)
+ it 'allows the body to be read using #body' do
+ response.body.to_s.should =~ expected_regex
end
- after(:all) do
- @orig_webmock_callbacks.each do |cb|
- ::WebMock::CallbackRegistry.add_callback(cb[:options], cb[:block])
- end
+ it 'allows the body to be read using #read_body' do
+ response.read_body.to_s.should =~ expected_regex
end
- def self.it_allows_the_body_to_be_read_again
- subject { @response.clone }
- let(:expected_regex) { /You have reached this web page by typing.*example\.com/ }
+ it 'allows the body to be read using #read_body with a block' do
+ yielded_body = ''
+ ret_val = response { |r| r.read_body { |s| yielded_body << s.to_s } }
+ yielded_body.should =~ expected_regex
+ end
- it 'allows the body to be read using #body' do
- subject.body.to_s.should =~ expected_regex
- end
+ it 'allows the body to be read by passing a destination string to #read_body' do
+ dest = ''
+ ret_val = response { |r| r.read_body(dest) }.body
+ dest.to_s.should =~ expected_regex
+ ret_val.to_s.should == dest
+ end
- it 'allows the body to be read using #read_body' do
- subject.read_body.to_s.should =~ expected_regex
- end
+ it 'raises an ArgumentError if both a destination string and a block is given to #read_body' do
+ dest = ''
+ expect { response { |r| r.read_body(dest) { |s| } } }.should raise_error(ArgumentError, 'both arg and block given for HTTP method')
+ end
- it 'allows the body to be read using #read_body with a block' do
- yielded_body = ''
- ret_val = subject.read_body { |s| yielded_body << s }
- yielded_body.should =~ expected_regex
- ret_val.should be_instance_of(Net::ReadAdapter)
- end
+ it 'raises an IOError when #read_body is called twice with a block' do
+ response { |r| r.read_body { |s| } }
+ expect { response { |r| r.read_body { |s| } } }.to raise_error(IOError, /read_body called twice/)
+ end
- it 'allows the body to be read by passing a destination string to #read_body' do
- dest = ''
- ret_val = subject.read_body(dest)
- dest.should =~ expected_regex
- ret_val.should == dest
- end
+ it 'raises an IOError when #read_body is called twice with a destination string' do
+ dest = ''
+ response { |r| r.read_body(dest) }
+ expect { response { |r| r.read_body(dest) } }.to raise_error(IOError, /read_body called twice/)
+ end
+ end
- it 'raises an ArgumentError if both a destination string and a block is given to #read_body' do
- dest = ''
- expect { subject.read_body(dest) { |s| } }.should raise_error(ArgumentError, 'both arg and block given for HTTP method')
- end
+ { :get => /You have reached this web page by typing.*example\.com/, :head => /\A\z/ }.each do |http_verb, expected_body_regex|
+ context "for a #{http_verb.to_s.upcase} request" do
+ let(:http_verb_method) { :"request_#{http_verb}" }
- it 'raises an IOError when #read_body is called twice with a block' do
- subject.read_body { |s| }
- expect { subject.read_body { |s| } }.to raise_error(IOError, /read_body called twice/)
- end
+ def response(&block)
+ if @response && block
+ block.call(@response)
+ return @response
+ end
- it 'raises an IOError when #read_body is called twice with a destination string' do
- dest = ''
- subject.read_body(dest)
- expect { subject.read_body(dest) }.to raise_error(IOError, /read_body called twice/)
+ @response ||= begin
+ http = Net::HTTP.new('example.com', 80)
+ res = http.send(http_verb_method, '/', &block)
+ res.should_not be_a(VCR::Net::HTTPResponse)
+ res.should_not be_a(::WebMock::Net::HTTPResponse)
+ res
+ end
end
- end
- context 'when the body has already been read using #read_body and a dest string' do
- before(:each) do
- http = Net::HTTP.new('example.com', 80)
- dest = ''
- @response = http.request_get('/') { |res| res.read_body(dest) }
- @response.extend VCR::Net::HTTPResponse
+ context 'when the body has not already been read' do
+ it_allows_the_body_to_be_read(expected_body_regex)
end
- it_allows_the_body_to_be_read_again
- end
+ context 'when the body has already been read using #read_body and a dest string' do
+ before(:each) do
+ dest = ''
+ response { |res| res.read_body(dest) }
+ response.extend VCR::Net::HTTPResponse
+ end
- context 'when the body has already been read using #body' do
- before(:each) do
- http = Net::HTTP.new('example.com', 80)
- @response = http.request_get('/')
- @response.body
- @response.extend VCR::Net::HTTPResponse
+ it_allows_the_body_to_be_read(expected_body_regex)
end
- it_allows_the_body_to_be_read_again
+ context 'when the body has already been read using #body' do
+ before(:each) do
+ response.body
+ response.extend VCR::Net::HTTPResponse
+ end
+
+ it_allows_the_body_to_be_read(expected_body_regex)
+ end
end
end
end

0 comments on commit a3d79c6

Please sign in to comment.