#ruby #rspec #mixins #stubbing
#ruby #rspec #миксины #заглушка
Вопрос:
У меня есть модуль, который включен в другой модуль, и оба они реализуют один и тот же метод. Я хотел бы заглушить метод включенного модуля, что-то вроде этого:
module M
def foo
:M
end
end
module A
class << self
include M
def foo
super
end
end
end
describe "trying to stub the included method" do
before { allow(M).to receive(:foo).and_return(:bar) }
it "should be stubbed when calling M" do
expect(M.foo).to eq :bar
end
it "should be stubbed when calling A" do
expect(A.foo).to eq :bar
end
end
Первый тест пройден, но второй выводит:
Failure/Error: expect(A.foo).to eq :bar
expected: :bar
got: :M
Почему заглушка не работает в этом случае?
Есть ли другой способ добиться этого?
Спасибо!
————————————-ОБНОВИТЬ———————————-
Спасибо! использование allow_any_instance_of(M) решило эту проблему. Мой следующий вопрос — что произойдет, если я использую prepend, а не include? смотрите следующий код:
module M
def foo
super
end
end
module A
class << self
prepend M
def foo
:A
end
end
end
describe "trying to stub the included method" do
before { allow_any_instance_of(M).to receive(:foo).and_return(:bar) }
it "should be stubbed when calling A" do
expect(A.foo).to eq :bar
end
end
На этот раз использование allow_any_instance_of(M) приводит к бесконечному циклу. почему это так?
Ответ №1:
Обратите внимание, что вы не можете вызвать напрямую M.foo
! Кажется, что ваш код работает только потому, что вы издевались M.foo
над return :bar
.
Когда вы открываете A
metaclass ( class << self
) для включения M
, вы должны издеваться над любым экземпляром M
, который добавляется к вашему before
блоку:
allow_any_instance_of(M).to receive(:foo).and_return(:bar)
module M
def foo
:M
end
end
module A
class << self
include M
def foo
super
end
end
end
describe "trying to stub the included method" do
before do
allow(M).to receive(:foo).and_return(:bar)
allow_any_instance_of(M).to receive(:foo).and_return(:bar)
end
it "should be stubbed when calling M" do
expect(M.foo).to eq :bar
end
it "should be stubbed when calling A" do
expect(A.foo).to eq :bar
end
end
Комментарии:
1. Это работает. По-видимому, в отличие
allow
от,allow_any_instance_of
не требует определения метода для объекта.2. я думаю, это просто помогло мне решить проблему, связанную с более чем 5 часами ударов головой о стол. Спасибо!
3. Ср.,
expect_any_instance_of
… это навело меня на правильный путь