В RSpec, в частности, версия> = 3, есть ли разница между:RSpec разрешить/ожидать против просто ожидать/and_return
- Использование
allow
для установки ожидания сообщения с параметрами, которые возвращают тестовые двойников, а затем с помощьюexpect
сделать утверждение о возвращенном тесте удваивается - Просто используя
expect
настроить ожидания с параметрами и вернуть тест двойной
или все это просто семантика? Я знаю, что предоставление/указание возвращаемого значения с expect
было the syntax in RSpec mocks 2.13, но, насколько я вижу, the syntax changed in RSpec mocks 3 использовать allow
.
Однако в (прохождение) образец кода ниже, с использованием либо allow
/expect
или просто expect
/and_return
кажется, чтобы генерировать один и тот же результат. Если один синтаксис был предпочитать другой, возможно, я бы ожидал там быть какой-то устаревания уведомления, но так как это не так, то, казалось бы, что оба Синтаксисы считаются действительными:
class Foo
def self.bar(baz)
# not important what happens to baz parameter
# only important that it is passed in
new
end
def qux
# perform some action
end
end
class SomethingThatCallsFoo
def some_long_process(baz)
# do some processing
Foo.bar(baz).qux
# do other processing
end
end
describe SomethingThatCallsFoo do
let(:foo_caller) { SomethingThatCallsFoo.new }
describe '#some_long_process' do
let(:foobar_result) { double('foobar_result') }
let(:baz) { double('baz') }
context 'using allow/expect' do
before do
allow(Foo).to receive(:bar).with(baz).and_return(foobar_result)
end
it 'calls qux method on result of Foo.bar(baz)' do
expect(foobar_result).to receive(:qux)
foo_caller.some_long_process(baz)
end
end
context 'using expect/and_return' do
it 'calls qux method on result of Foo.bar(baz)' do
expect(Foo).to receive(:bar).with(baz).and_return(foobar_result)
expect(foobar_result).to receive(:qux)
foo_caller.some_long_process(baz)
end
end
end
end
Если я сознательно сделать что тесты не путем изменения Переданного baz
параметра в ожидании на другой двойной тест, ошибки в значительной степени то же самое:
1) SomethingThatCallsFoo#some_long_process using allow/expect calls quux method on result of Foo.bar(baz)
Failure/Error: Foo.bar(baz).qux
<Foo (class)> received :bar with unexpected arguments
expected: (#<RSpec::Mocks::Double:0x3fe97a0127fc @name="baz">)
got: (#<RSpec::Mocks::Double:0x3fe97998540c @name=nil>)
Please stub a default value first if message might be received with other args as well.
# ./foo_test.rb:16:in `some_long_process'
# ./foo_test.rb:35:in `block (4 levels) in <top (required)>'
2) SomethingThatCallsFoo#some_long_process using expect/and_return calls quux method on result of Foo.bar(baz)
Failure/Error: Foo.bar(baz).qux
<Foo (class)> received :bar with unexpected arguments
expected: (#<RSpec::Mocks::Double:0x3fe979935fd8 @name="baz">)
got: (#<RSpec::Mocks::Double:0x3fe979cc5c0c @name=nil>)
# ./foo_test.rb:16:in `some_long_process'
# ./foo_test.rb:43:in `block (4 levels) in <top (required)>'
Итак, есть ли какие-либо реальные различия между этими двумя тестами, либо в результате или выраженное намерение, или это просто семантика и/или личное предпочтение? Должен ли allow
/expect
использоваться по сравнению с expect
/and_return
в целом, поскольку он выглядит синтаксисом замены или каждый из них предназначен для использования в конкретных тестовых сценариях?
Update
После прочтения Mori's answer «с, я закомментировал Foo.bar(baz).qux
строки из кода примера выше, и получили следующие ошибки:
1) SomethingThatCallsFoo#some_long_process using allow/expect calls qux method on result of Foo.bar(baz)
Failure/Error: expect(foobar_result).to receive(:qux)
(Double "foobar_result").qux(any args)
expected: 1 time with any arguments
received: 0 times with any arguments
# ./foo_test.rb:34:in `block (4 levels) in <top (required)>'
2) SomethingThatCallsFoo#some_long_process using expect/and_return calls qux method on result of Foo.bar(baz)
Failure/Error: expect(Foo).to receive(:bar).with(baz).and_return(foobar_result)
(<Foo (class)>).bar(#<RSpec::Mocks::Double:0x3fc211944fa4 @name="baz">)
expected: 1 time with arguments: (#<RSpec::Mocks::Double:0x3fc211944fa4 @name="baz">)
received: 0 times
# ./foo_test.rb:41:in `block (4 levels) in <top (required)>'
allow
спецификации терпит неудачу, потому чтоfoobar_result
Двойной никогда не заходит за результатFoo.bar(baz)
, и, следовательно, никогда не имеет#qux
, вызвавшего егоexpect
спекуляция терпит неудачу в точкеFoo
никогда не получать.bar(baz)
так что мы даже не добраться до точки допрашиватьfoobar_result
двойной
Имеет смысл: это не просто изменение синтаксиса, и что expect
/and_return
действительно имеет цель отличается от allow
/expect
.Я действительно должен был проверить самое очевидное место: RSpec Mocks README, в частности, следующие разделы: