Skip to content

Commit

Permalink
Add WebMock.globally_stub_request.
Browse files Browse the repository at this point in the history
This allows easier integration with WebMock by another library like VCR so it can register a global hook to handle every request.
  • Loading branch information
myronmarston committed Nov 18, 2011
1 parent 8786b65 commit 2fe6808
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 1 deletion.
19 changes: 18 additions & 1 deletion lib/webmock/stub_registry.rb
Expand Up @@ -4,13 +4,30 @@ class StubRegistry
include Singleton

attr_accessor :request_stubs
attr_accessor :global_stub

def initialize
reset!
end

def reset!
self.request_stubs = []
self.request_stubs = global_stub ? [global_stub] : []
end

def global_stub_block=(block)
self.global_stub = ::WebMock::RequestStub.new(:any, /.*/)

# This hash contains the responses returned by the block,
# keyed by the exact request (using the object_id).
# That way, there's no race condition in case #to_return
# doesn't run immediately after stub.with.
responses = {}

self.global_stub.with { |request|
responses[request.object_id] = block.call(request)
}.to_return(lambda { |request| responses.delete(request.object_id) })

register_request_stub(self.global_stub)
end

def register_request_stub(stub)
Expand Down
4 changes: 4 additions & 0 deletions lib/webmock/webmock.rb
Expand Up @@ -88,6 +88,10 @@ def self.print_executed_requests
puts WebMock::RequestExecutionVerifier.executed_requests_message
end

def self.globally_stub_request(&block)
WebMock::StubRegistry.instance.global_stub_block = block
end

%w(
allow_net_connect!
disable_net_connect!
Expand Down
50 changes: 50 additions & 0 deletions spec/acceptance/shared/stubbing_requests.rb
Expand Up @@ -287,6 +287,56 @@
end
end

describe "when stubbing request with a global hook" do
after(:each) do
WebMock::StubRegistry.instance.global_stub = nil
end

it 'returns the response returned by the hook' do
WebMock.globally_stub_request do |request|
{ :body => "global stub body" }
end

http_request(:get, "http://www.example.com/").body.should == "global stub body"
end

it 'does not get cleared when a user calls WebMock.reset!' do
WebMock.globally_stub_request do |request|
{ :body => "global stub body" }
end
WebMock.reset!
http_request(:get, "http://www.example.com/").body.should == "global stub body"
end

it "does not stub the request if the hook does not return anything" do
WebMock.globally_stub_request { |r| }
lambda {
http_request(:get, "http://www.example.com/")
}.should raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://www.example.com/))
end

it "passes the request to the block" do
passed_request = nil
WebMock.globally_stub_request do |request|
passed_request = request
{ :body => "global stub body" }
end

http_request(:get, "http://www.example.com:456/bar")
passed_request.uri.to_s.should == "http://www.example.com:456/bar"
end

it "should call the block only once per request" do
call_count = 0
WebMock.globally_stub_request do |request|
call_count += 1
{ :body => "global stub body" }
end
http_request(:get, "http://www.example.com/")
call_count.should == 1
end
end

describe "when stubbing request with a block evaluated on request" do
it "should match if block returns true" do
stub_request(:get, "www.example.com").with { |request| true }
Expand Down

0 comments on commit 2fe6808

Please sign in to comment.