Suppose I have this very simple method in Store's model:
def geocode_address
loc = Store.geocode(address)
self.lat = loc.lat
self.lng = loc.lng
end
If I want to write some test scripts that aren't affected by the geocoding service, which may be down, have limitations or depend on my internet connection, how do I mock out the geocoding service? If I could pass a geocoding object into the method, it would be easy, but I don't see how I could do it in this case.
Thanks!
Tristan
If you want to mock an object for the duration of your entire test function, you can use patch() as a function decorator. These functions are now in their own file, separate from their tests. Next, you'll re-create your tests in a file called tests.py .
We can use Mockito class mock() method to create a mock object of a given class or interface. This is the simplest way to mock an object. We are using JUnit 5 to write test cases in conjunction with Mockito to mock objects.
using rspecs built in mocking and stubbing, you could do something like this:
setup do
@subject = MyClass.new
end
it 'handles geocoder success' do
mock_geo = mock('result', :lat => 1, :lng => 1)
Store.stub!(:geocode).and_return mock_geo
@subject.geocode_address
@subject.lat.should == mock_geo.lat
@subject.lng.should == mock_geo.lng
end
it 'handles geocoder errors' do
Store.stub!(:geocode).and_raise Exception
@subject.geocode_address
@subject.lat.should == _something_reasonable_
@subject.lng.should == _something_reasonable_
end
Using Double-R (RR) https://github.com/btakita/rr, it's simple:
test 'should mock the geocoding service' do
store = Store.new
mock_location = mock(Object.new)
mock_location.lat{1.234}
mock_location.lng{5.678}
mock(Store).geocode.with_any_args{mock_location}
store.geocode_address
assert_equal 1.234, store.lat
assert_equal 5.678, store.lng
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With