Using Rack middleware, we can reroute Rack::Test
requests to
fake remote services without spinning up servers. This example shows how to use
that technique to handle the Transparent Redirect HTTP requests
for the Braintree payment gateway.
How Rack::Test works
Our typical integration test stack is RSpec and Capybara. We use different drivers for different situations, such as Capybara Webkit when we need to run JavaScript in a headless browser.
The default driver for Capybara is Rack::Test
. It is one of the fastest
drivers because it interacts directly with Rack interfaces and doesn’t require
an external service to be started.
Out of the box, Rack::Test
will hit the same Rack application for every
request. So, we’ll use Rack middleware to re-route Rack::Test
requests based
on their port number.
PortMap Rack middleware
Middleware to re-route requests based on their port number:
class PortMap
def initialize(default_app, mappings)
@default_app = default_app
@mappings = mappings
end
def call(env)
request = Rack::Request.new(env)
port = request.port
app = @mappings[port] || @default_app
app.call(env)
end
end
We can now use this in a Capybara + Rack::Test
suite:
original_app = Capybara.app
Capybara.app = PortMap.new(
original_app,
1234 => MyFakeCreditCardGateway,
5678 => MyFakeOauthServer
)
FakeBraintree
To use PortMap
more specifically for the Transparent Redirect use case, we
would include FakeBraintree, a library we maintain. It is a
fake for the Braintree gateway.
This will now route Braintree requests to FakeBraintree
:
Capybara.app = PortMap.new(
original_app,
ENV['GATEWAY_PORT'] => FakeBraintree::SinatraApp
)
Similar middleware
We could also write middleware to reroute requests based on the host name, path, or anything else in the request, faking remote services without spinning up servers.
What’s next
If you found this useful, you might also enjoy: