Вы в корне неправильно поняли, что allow_any_instance_of
и to_return
делают.
allow_any_instance_of
используется для заглушки метода в любом экземпляре данного класса. Это не устанавливает никаких ожиданий - expect_any_instance_of
делает.
class Foo
def bar(*args)
"baz"
end
end
RSpec.describe Foo do
describe "allow_any_instance_of" do
it "does not create an expectation" do
allow_any_instance_of(Foo).to receive(:bar).and_call_original
expect(true).to be_truthy
end
end
describe "expect_any_instance_of" do
it "sets an expectation" do
expect_any_instance_of(Foo).to receive(:bar).and_call_original
expect(Foo.new.bar).to eq 'baz'
end
# this example will fail
it "fails if expected call is not sent" do
expect_any_instance_of(Foo).to receive(:bar).and_call_original
expect(true).to be_truthy
end
end
end
.and_return
используется для установки значения возврата макета / заглушки. Это не так, как вы, кажется, полагаете, установить ожидание возвращаемого значения.
RSpec.describe Foo do
describe "and_return" do
it "changes the return value" do
allow_any_instance_of(Foo).to receive(:bar).and_return('hello world')
expect(Foo.new.bar).to_not eq 'baz'
expect(Foo.new.bar).to eq 'hello world'
end
end
end
Вы можете использовать .and_call_original
, если хотите шпионить за методом без изменения его возвращаемого значения. По умолчанию любой метод, вставленный в allow_any_instance_of/expect_any_instance
, вернет nil.
AFAIK Невозможно установить ожидаемое значение, равное .and_call_original
. Это одна из причин, по которой any_instance_of
считается запахом кода, и его следует избегать.