Как я могу заглушить зависимость в сервисе Rails
Я имею:
- оболочка веб-сервиса, которая вызывает сторонний API (lib)
- сервис, который вызывает эту обертку и делает некоторую путаницу (сервис)
Тестирование класса lib с помощью VCR прекрасно работает, но я не уверен, как протестировать сервис. В частности, как я могу заглушить вызов API внутри службы?
class GetBazsForBars
def self.call(token)
bazs = Foo.new(token).bars
# do some other stuff
bazs
end
end
И тест:
require 'rails_helper'
RSpec.describe GetBazsForBars, type: :service do
describe ".call" do
let(:token) { Rails.configuration.x.test_token }
let(:bazs) { GetBazsForBars.call(token) }
it { expect(bazs.any?).to eq(true) }
end
end
Я предпочел бы не переходить в Foo на службу.
В Payola автор использует StripeMock для подведения итогов ответов. Могу ли я написать что-то подобное, например, FooMock, который вызывает видеомагнитофон и использует сервис вместо этого?
Не уверен, как это сделать с Ruby, я привык к C# / Java DI, передавая конструкторам.
Спасибо за помощь.
Обновить
Перешел на полный ответ
2 ответа
foo = double(bars: 'whatever')
allow(Foo).to receive(:new).with(:a_token).and_return foo
или же
allow(Foo).to receive(:new).with(:a_token)
.and_return double(bar: 'whatever')
@mori обеспечил хорошую отправную точку, и я закончил...
1) заглушка const имени сервиса:
require 'rails_helper'
RSpec.describe GetBazsForBars, type: :service do
describe ".call" do
before { stub_const("Foo", FakeFoo) } # <-- added this
let(:token) { Rails.configuration.x.test_token }
let(:bazs) { GetBazsForBars.call(token) }
it { expect(bazs.any?).to eq(true) }
end
end
2) создание поддельной оболочки foo в /spec/fakes:
class FakeFoo < Foo
def bars
VCR.use_cassette("foo_bars") do
super()
end
end
end
Это означает, что в моем служении я могу просто Foo.new
и он обрабатывает тест и реальную жизнь одинаково (отличный интеграционный тест). И у меня не было никаких цепочек насмешек в тесте, которые потребовали бы реального экземпляра для правильного вызова VCR.
Там может быть более простой способ, но код выглядит довольно хорошо для меня, так что отправьте его.