Toggleable Fakes for better integration testing
30 Sep 2014During the development of iOS Project Monitor, I ran into the need to test against a few third party services. Engineyard’s Andy Delcambre gave a great talk on how to use test matrices and fake services to write one test that hits both your fake and the service.
Most people leap towards WebMock or VCR to test against services. This is an alternate approach that is a little more upfront work but adds incredible confidence in your code.
Overview
- Create a
FakeThirdParty
service.
require 'sinatra/base'
class FakePusher < Sinatra::Base
post "/apps/:app_id/events", provides: :json do
JSON.parse(request.body.read)
{}.to_json
end
# start the server if ruby file executed directly
run! if app_file == $0
end
class FakeError
def self.call(env)
[ 503, { 'Content-Type' => 'application/json' }, [{ "error" => "server error" }.to_json] ]
end
end
class FakeUnauthorized
def self.call(env)
[ 401, { 'Content-Type' => 'application/json' }, [{"error"=>"unauthorized"}.to_json] ]
end
end
- Using WebMock, route all traffic to
www.thirdparty.com
to our sinatra fake. Take note of the.to_rack
method:
require 'webmock/rspec'
module FakeSpecHelpers
def servers_return_healthy
puts "WARNING: Stubbing out healthy servers"
WebMock.stub_request(:any, /.*api.pusherapp.com\/.*/).to_rack(FakePusher)
end
def servers_return_error
WebMock.stub_request(:any, /.*/).to_rack(FakeError)
end
def servers_return_unauthorized
WebMock.stub_request(:any, /.*/).to_rack(FakeUnauthorized)
end
end
RSpec.configure do |config|
config.include FakeSpecHelpers
config.before(:each) do
if ENV["INTEGRATION"] == "true"
WebMock.allow_net_connect!
else
WebMock.disable_net_connect!
servers_return_healthy
end
end
end
- Using an environment variable,
INTEGRATION=true
, you can turn off the WebMock routing and have the tests hit the real service.
Challenges
- Performing a Tear down, or cleaning, your third party test environment can be hard, if not impossible.
- Data from one test can then pollute other tests.
For something a little more elaborate, check out iOS Project Monitor’s Fake Parse Service and the WebMock Routing.
[16M05] Toggleable Mocks and Testing Strategies in a Service Oriented Architecture (en) from rubykaigi on Vimeo.