Webmock is a neat library for stubbing out http requests in your application so as not to have to make real ones during your testing. Normally in one of your models or controllers you would be making a request to some external webservice say google.

stub_request(:get, "http://google.com").to_return("some string")

and then anywhere you make an http request to http://google.com in your application you get returned "some string". Neat. However we can abuse this to do something more interesting with Rack::Test. Rack::Test provides


methods to interact with your system without having to spin up a real server and the overhead that entail. However if you have a complex protocol to test for which a ruby client library exists,
it would be nice to bridge the client library into Rack::Test so that you can use it directly instead of having to reinvent the wheel and call :get, :post, etc directly.


Using Webmock this turns out to be very easy and is shown in the code below.

module HttpToRack
    # @param method [Symbol] the http method to bridge to Rack::Test.
    # @param uri [String] the end point to intercept
    def http_to_rack(method, uri)

      stub_request(method, uri).to_return( lambda { |request|

        case request.method
        when :post
          post request.uri.path, request.body, request.headers
        when :put
          post request.uri.path, request.body, request.headers
        when :get
          get request.uri.path, request.headers
        when :delete
          delete request.uri.path, request.headers
        when :head
          head request.uri.path, request.headers
          raise "#{request.method} not supported"

        { :body => response.body, 
          :headers => response.headers 


If you are testing your pingback route for an integration test and there is some class PingBackDriver that does some fancy XMLRPC for example that the pingback route responds to then you can use PingBackDriver directly but use httptorack to bridge those specific calls to Rack::Test

 it "should follow the pingback protocol http://www.hixie.ch/specs/pingback/pingback-1.0 " do

   # The post that is the target of the pingback
   http_to_rack :any, "http://www.example.com/posts/1"

   # The pingback server
   http_to_rack :any, "http://www.example.com/pingback"

   PingBackDriver.ping \
            :source_uri => "http://www.example.com/posts/2", 
            :target_uri => "http://www.example.com/posts/1"