Rails Geocoder Testing with rspec
Asked Answered
W

2

9

I am trying to set up my RSpec tests to use stubs rather then using networking to do the geocoding.

I added this:

before(:each) do
Geocoder.configure(:lookup => :test)
Geocoder::Lookup::Test.add_stub(
    "Los Angeles, CA", [{
                            :latitude    => 34.052363,
                            :longitude    => -118.256551,
                            :address      => 'Los Angeles, CA, USA',
                            :state        => 'California',
                            :state_code   => 'CA',
                            :country      => 'United States',
                            :country_code => 'US'
                        }],

)

end

I am using FactoryGirl to create the test data like so:

FactoryGirl.define do
    factory :market do
    city 'Los Angeles'
    state 'CA'
    radius 20.0
  end
end

The latitude/longitude are correctly being geocoded and stored in latitude/longitude. However, when I try:

Market.near(params[:search])

it returns nil.. But, if I just use the lookup => :google it works just as I intend it to. Has anyone got this working before, specifically the near method of geocoder?

Weakling answered 9/9, 2015 at 21:51 Comment(2)
did you ever figure this out? I am running into the exact same issue nowLikelihood
@AlexNeigher See my answer below.Weakling
W
8

I ended up coming back to this on a new project and figured it out.

The docs on geocoder actually state that the hash has to have string keys and not symbols. geocoder docs - see notes

i.e.

before(:each) do
    Geocoder.configure(:lookup => :test)
    Geocoder::Lookup::Test.add_stub(
        "Los Angeles, CA", [{
                                "latitude"    => 34.052363,
                                "longitude"    => -118.256551,
                                "address"      => 'Los Angeles, CA, USA',
                                "state"        => 'California',
                                "state_code"   => 'CA',
                                "country"      => 'United States',
                                "country_code" => 'US'
                            }],

    )
end

and not how I did it in the original post:

i.e. :latitude => 34.052363

I ended up doing something a bit more dynamic:

# frozen_string_literal: true

module GeocoderStub
  def self.stub_with(facility)
    Geocoder.configure(lookup: :test)

    results = [
      {
          'latitude' => Faker::Address.latitude.first(9),
          'longitude' => Faker::Address.longitude.first(9)
      }
    ]

    queries = [facility.full_address, facility.zip]
    queries.each { |q| Geocoder::Lookup::Test.add_stub(q, results) }
  end
end

and in my factory:

require './spec/support/geocoder_stub'

FactoryGirl.define do
  factory :facility do
    name { Faker::Company.name }
    rating { rand(1..5) }
    street { Faker::Address.street_address }
    city { Faker::Address.city }
    state { Faker::Address.state }
    zip { Faker::Address.zip_code }

    after(:build) { |facility| GeocoderStub.stub_with(facility) }
  end
end

This adds a geocoder stub for every Facility factory that is built for both full address (method defined in facility) and zip.

Weakling answered 8/11, 2017 at 5:11 Comment(2)
:heart: :heart: :heart:Coulomb
the best solution is using vcr to stub all http requestsSeton
T
0

I found a simpler approach to be just stubbing everything with the same values by default:

# test/test_helper.rb
Geocoder.configure(lookup: :test)
Geocoder::Lookup::Test.set_default_stub([{ coordinates: [40.7143528, -74.0059731] }])

Also, to avoid unnecessary calls, it's also a good idea to restrict your callbacks:

class Account < ActiveRecord
after_validation :geocode, if: ->(obj) { obj.address.present? and obj.address_changed? }
end

Source: https://github.com/alexreisner/geocoder#testing

Tahiti answered 1/2, 2022 at 22:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.