Skip to content

Instantly share code, notes, and snippets.

@glittershark
Forked from paveltyk/mock_geocoder.rb
Last active April 12, 2019 09:04
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save glittershark/11e39bf5808fffffbbc3 to your computer and use it in GitHub Desktop.
Save glittershark/11e39bf5808fffffbbc3 to your computer and use it in GitHub Desktop.
Mock geocoding in Rspec, using the new 'expect' syntax
# In spec_helper:
# RSpec.configure do |config|
# ...
# config.include(MockGeocoder)
# end
#
# In your tests:
# it 'mock geocoding' do
# # You may pass additional params to override defaults
# # (i.e. :coordinates => [10, 20])
# mock_geocoding!
# address = Factory(:address)
# address.lat.should eq(1)
# address.lng.should eq(2)
# end
require 'geocoder/results/base'
module MockGeocoder
def self.included(base)
base.before :each do
allow(::Geocoder).to receive(:search).and_raise(
RuntimeError.new 'Use "mock_geocoding!" method in your tests.')
end
end
def mock_geocoding!(options = {})
options.reverse_merge!(
address: 'Address',
coordinates: [1, 2],
state: 'State',
state_code: 'State Code',
country: 'Country',
country_code: 'Country code'
)
MockResult.new.tap do |result|
options.each do |prop, val|
allow(result).to receive(prop).and_return(val)
end
allow(Geocoder).to receive(:search).and_return([result])
end
end
class MockResult < ::Geocoder::Result::Base
def initialize(data = [])
super(data)
end
end
end
@neumachen
Copy link

Actually, what if I wanted to add more than one result? So I can simulate a near me or something?

@duffuniverse
Copy link

Thank you.

@duffuniverse
Copy link

require 'ostruct'

def mock_geocoding!(options = {})
    ...

    MockResult.new.tap do |result|
      result = OpenStruct.new(options)
      allow(Geocoder).to receive(:search).and_return([result])
    end
end

@nicolasrouanne
Copy link

nicolasrouanne commented Mar 5, 2018

Thanks for this very useful mock!

I ran into some troubles though when using Google Geocoding service:

  • it's based on ::Geocoder::Result::Base which doesn't provide some more specific Google accessors such as address_components
  • it doesn't mock the #data method which is publicly available in the gem when using Google Geocoding API (and that my code used)

I made a fork of this gist which makes these changes, though implementing the #data method in a rather simplistic way.

@Loschcode
Copy link

I don't really know what it's worth but I added this line

allow(result).to receive(:data).and_return(options) because I use Geocoder.search('ip').first.data in my own code and it's not mocked in your gist, thank you very much for the rest ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment