Как мне издеваться над объектом в этом случае? нет очевидного способа заменить объект на макет - PullRequest
5 голосов
/ 02 февраля 2011

Предположим, у меня есть очень простой метод в модели Store:

  def geocode_address
      loc = Store.geocode(address)
    self.lat = loc.lat
    self.lng = loc.lng
  end

Если я хочу написать несколько тестовых сценариев, которые не затронуты службой геокодирования, которые могут быть недоступны, иметь ограничения или зависеть от моего интернет-соединения, как мне смоделировать службу геокодирования? Если бы я мог передать объект геокодирования в метод, это было бы легко, но я не понимаю, как я мог бы сделать это в этом случае.

Спасибо!
Тристан

Ответы [ 3 ]

8 голосов
/ 02 февраля 2011

используя rspecs, встроенные в насмешки и заглушки, вы можете сделать что-то вроде этого:

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
2 голосов
/ 02 февраля 2011

Использование Double-R (RR) https://github.com/btakita/rr, это просто:

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
0 голосов
/ 02 февраля 2011

Если нет способа издеваться над сервисом, значит, он плохой.Сервис должен быть отделен от модели (какой бы Store ни был).Вам просто нужно провести рефакторинг в более несвязанную систему, которая позволит вам высмеивать ее и упрощает обслуживание системы.

...