FakeWeb

20 September 2011

I was testing a client I wrote to a server API recently. Being relatively new to testing with RSpec and Ruby, I initially took the naive approach of building a node.js application to behave as a dummy test server.

Originally when I wrote the code I knew there had to be a better way, but I only found that better way today.

I was revisiting some of that code and discovered FakeWeb. It’s a Ruby framework that makes it simple to test code that involves HTTP requests. It intercepts HTTP calls made through Net::HTTP and makes it dead simple to create predictable responses for those calls.

This means that tests that would have been regarded as integration tests before can be isolated from the dependency on an external server and can be executed as unit tests. Big win!

Here’s a sample of how it works in context of RSpec:

before do
  FakeWeb.allow_net_connect = false
  register_body = {
    :id => 1
  }.to_json
  FakeWeb.register_uri(:post, 'http://localhost/register', :body => register_body)
end

The first line in the before block tells FakeWeb to disallow any real network connections from happening. Every ‘connection’ must be handled inside FakeWeb. An exception is raised if a request can’t be handled by FakeWeb directly.

The register_body variable simply contains the key-value pairs to be returned in the HTTP response’s body as JSON.

FakeWeb.register_uri then registers a verb and URI to be handled by FakeWeb, and sets the body of the response. It’s also possible to set a status code and to handle :any verb.

Once the URI has been registered, any call made to that URI from Net::HTTP will be responded to by FakeWeb.

My tests are now running marginally faster and are far less flaky since all the external dependencies are now being substituted with a controlled and predictable stub.

To get going, just add the gem to your Gemfile and run bundler:

gem 'fakeweb'

Also check out the FakeWeb docs at RubyForge