Skip to content
Browse files

Fix #to_rack to handle non-array response bodies.

When using #to_rack with a Rails endpoint, such as:

  stub_request(:any, %r{api.example.com/.*}).to_rack(Rails.application)

...you receive the following error:

  NoMethodError: undefined method `join' for #<ActionDispatch::Response:0x007ffd06e6f540>

Turns out ActionDispatch::Response is in the right. A Rack response body
is only required to implement #each, not #join.

This patch fixes #to_rack to build the body using the #each method.
  • Loading branch information...
1 parent beb8c65 commit 146acef3ed900814d67595950504295c760fbe15 Tammer Saleh committed Jan 18, 2012
Showing with 29 additions and 2 deletions.
  1. +7 −1 lib/webmock/rack_response.rb
  2. +14 −1 spec/support/my_rack_app.rb
  3. +8 −0 spec/unit/rack_response_spec.rb
View
8 lib/webmock/rack_response.rb
@@ -10,12 +10,18 @@ def evaluate(request)
status, headers, response = @app.call(env)
Response.new(
- :body => response.join,
+ :body => body_from_rack_response(response),
:headers => headers,
:status => status
)
end
+ def body_from_rack_response(response)
+ body = ""
+ response.each { |line| body << line }
+ return body
+ end
+
def build_rack_env(request)
uri = request.uri
headers = request.headers || {}
View
15 spec/support/my_rack_app.rb
@@ -1,18 +1,31 @@
require 'rack'
class MyRackApp
+ class NonArrayResponse
+ # The rack response body need not implement #join,
+ # but it must implement #each. It need not be an Array.
+ # ActionDispatch::Response, for example, exercises that fact.
+ # See: http://rack.rubyforge.org/doc/SPEC.html
+
+ def each(*args, &blk)
+ ["This is not in an array!"].each(*args, &blk)
+ end
+ end
+
def self.call(env)
case env.values_at('REQUEST_METHOD', 'PATH_INFO')
when ['GET', '/']
[200, {}, ["This is my root!"]]
when ['GET', '/greet']
name = env['QUERY_STRING'][/name=([^&]*)/, 1] || "World"
[200, {}, ["Hello, #{name}"]]
+ when ['GET', '/non_array_response']
+ [200, {}, NonArrayResponse.new]
when ['POST', '/greet']
name = env["rack.input"].read[/name=([^&]*)/, 1] || "World"
[200, {}, ["Good to meet you, #{name}!"]]
else
[404, {}, ['']]
end
end
-end
+end
View
8 spec/unit/rack_response_spec.rb
@@ -13,6 +13,14 @@
response.body.should include('This is my root!')
end
+ it "should behave correctly when the rack response is not a simple array of strings" do
+ request = WebMock::RequestSignature.new(:get, 'www.example.com/non_array_response')
+ response = @rack_response.evaluate(request)
+
+ response.status.first.should == 200
+ response.body.should include('This is not in an array!')
+ end
+
it "should send along params" do
request = WebMock::RequestSignature.new(:get, 'www.example.com/greet?name=Johnny')

0 comments on commit 146acef

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