W RSpec, szczególnie w wersji> = 3, jest jakaś różnica pomiędzy:RSpec pozwalają/oczekiwać vs tylko oczekiwać/and_return
- Korzystanie
allow
założyć oczekiwania wiadomość z parametrami, które zwracają podwójne testowe, a następnie za pomocąexpect
aby twierdzenie na zwróconej testu podwaja - tylko przy użyciu
expect
skonfigurować oczekiwanie z parametrami i powrócić test podwójnego
czy to wszystko to tylko semantyka? Wiem, że dostarczanie/określanie wartości zwracanej z expect
było the syntax in RSpec mocks 2.13, ale o ile widzę, the syntax changed in RSpec mocks 3 używać allow
.
Jednakże kod (przejście) próbki poniżej, stosując albo allow
/expect
lub tylko expect
/and_return
zdaje się generowania ten sam rezultat. Jeśli jeden składnia była przedkładana nad inną, być może bym się spodziewać tam być jakiś rodzaj uprzedzenia amortyzacji, ale ponieważ nie ma, wydaje się, że obie składnie są uznawane za ważne:
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
Gdybym celowo zrobić testy nie zmieniając przekazany w baz
parametru w oczekiwaniu na inną testowym podwójne, błędy są niemal tak samo:
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)>'
Więc, czy są jakieś istotne różnice między tymi dwoma badaniami, albo w wyniku lub wyrażone intencje, czy jest to tylko semantyka i/lub osobiste preferencje? Powinno się używać allow
/ ponad expect
/and_return
ogólnie, ponieważ wydaje się, że jest to zastępcza składnia, lub czy każda z nich ma być używana w konkretnych scenariuszach testowych?
Aktualizacja
Po przeczytaniu Mori's answer „s, wypowiedziało się w prostej linii z przykładowym kodzie Foo.bar(baz).qux
powyżej i dostał następujące błędy:
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
Spec nie działa, ponieważfoobar_result
double nigdy nie stanie się na skutekFoo.bar(baz)
, a więc nigdy nie ma#qux
nazwie goexpect
specyfikacja nie w punkcieFoo
nigdy otrzymaniu.bar(baz)
więc nawet nie dostać się do punktu odpytywaniafoobar_result
podwójne
ma sens: to nie tylko zmiana składni, a expect
/and_return
ma inny cel niż allow
/expect
.I naprawdę powinien mieć sprawdzone najbardziej oczywiste miejsce: RSpec Mocks README, a konkretnie w następujących sekcjach: