Skip to content
Browse files

Fix WebMock/Net::HTTP integration.

Rather than using a Net::HTTP monkey patch to record new requests, use WebMock's callback.  This prevents the monkey patches from colliding each other and ensures that VCR & WebMock work properly with Open URI.

Closes #14.
  • Loading branch information...
1 parent cbb493e commit aec21b49ee142520f6fd64cb7c7e8671d98e7306 @myronmarston committed Sep 25, 2010
View
11 features/net_http.feature
@@ -25,3 +25,14 @@ Feature: Net::HTTP
Given we do not have a "temp/block_with_a_return" cassette
When I make a returning block Net::HTTP get request to "http://example.com" while using the "temp/block_with_a_return" cassette
Then the "temp/block_with_a_return" library file should have a response for "http://example.com" that matches /You have reached this web page by typing.*example\.com/
+
+ Scenario: Record a request made with open uri
+ Given we do not have a "temp/open_uri" cassette
+ When I make an open uri Net::HTTP get request to "http://example.com" while using the "temp/open_uri" cassette
+ Then the "temp/open_uri" library file should have a response for "http://example.com" that matches /You have reached this web page by typing.*example\.com/
+
+ @copy_not_the_real_response_to_temp
+ Scenario: Replay a response for an open uri request
+ Given the "temp/not_the_real_response" library file has a response for "http://example.com" that matches /This is not the real response from example\.com/
+ When I make an open uri Net::HTTP get request to "http://example.com" while using the "temp/not_the_real_response" cassette
+ Then the response for "http://example.com" should match /This is not the real response from example\.com/
View
14 features/step_definitions/net_http_steps.rb
@@ -1,3 +1,5 @@
+require 'open-uri'
+
module NetHTTPHelpers
def perform_net_http_get_with_returning_block(uri, path)
Net::HTTP.new(uri.host, uri.port).request(Net::HTTP::Get.new(path, {})) do |response|
@@ -34,4 +36,14 @@ def result_body.body; self; end # make the string a fake response (so response.b
capture_response(url) do |uri, path|
perform_net_http_get_with_returning_block(uri, path)
end
-end
+end
+
+When /^I make an open uri Net::HTTP get request to "([^"]*)"$/ do |url|
+ capture_response(url) do |uri, path|
+ result = open(url)
+ # #open returns a StringIO rather than a Net::HTTPResponse, so we add #body to make it conform to the same interface
+ def result.body; read; end
+ result
+ end
+end
+
View
3 lib/vcr/http_stubbing_adapters/webmock.rb
@@ -1,5 +1,4 @@
require 'webmock'
-require 'vcr/extensions/net_http'
module VCR
module HttpStubbingAdapters
@@ -93,7 +92,7 @@ def checkpoints
end
end
-WebMock.after_request(:except => [:net_http], :real_requests_only => true) do |request, response|
+WebMock.after_request(:real_requests_only => true) do |request, response|
http_interaction = VCR::HTTPInteraction.new(
VCR::Request.new(
request.method,
View
4 spec/extensions/net_http_response_spec.rb
@@ -1,9 +1,7 @@
require 'spec_helper'
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! }
+ without_monkey_patches :all
def self.it_allows_the_body_to_be_read(expected_regex)
it 'allows the body to be read using #body' do
View
2 spec/extensions/net_http_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe "Net::HTTP Extensions" do
+ without_webmock_callbacks
+
let(:uri) { URI.parse('http://example.com') }
it 'checks if the request is stubbed using a VCR::Request' do
View
2 spec/http_stubbing_adapters/fakeweb_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe VCR::HttpStubbingAdapters::FakeWeb do
+ without_webmock_callbacks
+
it_should_behave_like 'an http stubbing adapter', ['net/http'], [:method, :uri, :host, :path]
describe '#should_unwind_response?' do
View
2 spec/http_stubbing_adapters/webmock_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe VCR::HttpStubbingAdapters::WebMock do
+ without_monkey_patches :vcr
+
it_should_behave_like 'an http stubbing adapter',
%w[net/http patron httpclient em-http-request],
[:method, :uri, :host, :path, :body, :headers]
View
31 spec/monkey_patches.rb
@@ -1,6 +1,13 @@
module MonkeyPatches
extend self
+ module RSpecMacros
+ def without_monkey_patches(scope)
+ before(:each) { MonkeyPatches.disable!(scope) }
+ after(:each) { MonkeyPatches.enable!(scope) }
+ end
+ end
+
NET_HTTP_SINGLETON = class << Net::HTTP; self; end
MONKEY_PATCHES = [
@@ -10,15 +17,27 @@ module MonkeyPatches
[NET_HTTP_SINGLETON, :socket_type]
]
- def enable!
- MONKEY_PATCHES.each do |mp|
- realias mp.first, mp.last, :with_monkeypatches
+ def enable!(scope)
+ case scope
+ when :all
+ MONKEY_PATCHES.each do |mp|
+ realias mp.first, mp.last, :with_monkeypatches
+ end
+ when :vcr
+ realias Net::HTTP, :request, :with_vcr
+ else raise ArgumentError.new("Unexpected scope: #{scope}")
end
end
- def disable!
- MONKEY_PATCHES.each do |mp|
- realias mp.first, mp.last, :without_monkeypatches
+ def disable!(scope)
+ case scope
+ when :all
+ MONKEY_PATCHES.each do |mp|
+ realias mp.first, mp.last, :without_monkeypatches
+ end
+ when :vcr
+ realias Net::HTTP, :request, :without_vcr
+ else raise ArgumentError.new("Unexpected scope: #{scope}")
end
end
View
4 spec/spec_helper.rb
@@ -8,8 +8,8 @@
require 'httpclient'
require 'em-http-request' unless RUBY_PLATFORM =~ /java/
require 'vcr'
-require 'vcr/http_stubbing_adapters/fakeweb'
require 'vcr/http_stubbing_adapters/webmock'
+require 'vcr/http_stubbing_adapters/fakeweb'
require 'rspec'
# Ruby 1.9.1 has a different yaml serialization format.
@@ -22,6 +22,8 @@
RSpec.configure do |config|
config.extend TempCassetteLibraryDir
config.extend DisableWarnings
+ config.extend MonkeyPatches::RSpecMacros
+ config.extend WebMockMacros
config.color_enabled = true
config.debug = RUBY_PLATFORM != 'java'
View
14 spec/support/webmock_macros.rb
@@ -0,0 +1,14 @@
+module WebMockMacros
+ def without_webmock_callbacks
+ before(:all) do
+ @original_webmock_callbacks = ::WebMock::CallbackRegistry.callbacks
+ ::WebMock::CallbackRegistry.reset
+ end
+
+ after(:all) do
+ @original_webmock_callbacks.each do |cb|
+ ::WebMock::CallbackRegistry.add_callback(cb[:options], cb[:block])
+ end
+ end
+ end
+end

0 comments on commit aec21b4

Please sign in to comment.
Something went wrong with that request. Please try again.