I’m working on a Rails app that uses the ym4r_gm plugin, getting Google to do the geocoding for Thentic. I liked the idea of stubbing the web service call, because all those calls to an external service add up to over 20 seconds of test suite run time(!). That’s almost half of the 50 second run time of my unit tests (and 50 seconds is much too long for a unit test suite).
I found a good starting point at geokit stubbing for faster tests. I also wanted a way to stub a geocoding failure, and a way to prevent any unit tests from using the real geocoding web service.
Here’s how I did it.
In test/test_helper.rb, add this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
class ActiveSupport::TestCase def setup GeoKit::Geocoders::MultiGeocoder.stubs(:geocode).raises(RuntimeError, 'Use mock_geocoding_success! or mock_geocoding_failure! in your test') end def mock_geocoding_success! geocode_payload = GeoKit::GeoLoc.new(:lat => 123.456, :lng => 123.456) geocode_payload.success = true GeoKit::Geocoders::MultiGeocoder.expects(:geocode).returns(geocode_payload) end def mock_geocoding_failure! geocode_payload = GeoKit::GeoLoc.new geocode_payload.success = false GeoKit::Geocoders::MultiGeocoder.expects(:geocode).returns(geocode_payload) end end |
What this does is to force you to choose either one of those mock_geocoding methods before you call the geocode method. To me this seems like a good idea since the integration tests that exercise the full application stack should probably be written using Cucumber and Webrat (which is what I’m using).
You will probably want to merge my one-line setup method into your existing setup code in test_helper, if any. Also note that this uses Mocha for mocking.