我很困惑为什么这个测试不起作用。它仅在我将返回值添加到存根
bar
方法时才有效。但是,预计不会有返回值,所以我只想测试bar
在foo
内被调用。
class Event < ApplicationRecord
def foo
bar
end
end
此测试无效。
describe Event, type: :model do
it 'calls bar' do
event = create(:event)
allow(event).to receive(:bar)
expect(event.foo).to receive(:bar)
end
end
Error message:
Failure/Error: expect(event.foo).to receive(:bar)
(nil).bar(*(any args))
expected: 1 time with any arguments
received: 0 times with any arguments
当我更改测试以添加返回值时,测试有效。
describe Event, type: :model do
it 'calls bar' do
event = create(:event)
allow(event).to receive(:bar).and_return(true)
expect(event.foo).to eq(true)
end
end
这张图有很多地方不对
让我们从方法开始:
class Event < ApplicationRecord
def foo
bar
end
end
当您调用
Event.new.foo
时,您是在#bar
上调用self
,这是Event的实例。不在方法上foo
.
如果你这样做
expect(event.foo).to receive(:bar)
你设置了对方法返回值的期望,这当然是行不通的。
如果你想测试调用 foo 调用 bar 你可以使用
expect(obj).to recieve :method_name
如果你想事先设置期望值:
describe Event, type: :model do
it 'calls bar' do
event = create(:event)
expect(event).to receive(:bar)
event.foo
end
end
请注意,除非您想存根该方法,否则不必使用
allow(event).to receive(:bar)
。 expect(event).to receive(:bar)
包装方法,以便 RSpec 可以跟踪对该方法的调用。
除非调用预期的方法,否则该示例将失败。
或者如果您更喜欢安排、行动、断言模式,您可以使用间谍:
describe Event, type: :model do
it 'calls bar' do
# arrange
event = create(:event)
allow(event).to receive(:bar)
# act
event.foo
# assert
expect(foo).to have_recieved(:bar)
end
end
不幸的是,这是错误的测试方式。您不需要模拟您的方法。就叫它吧
这是正确的做法。
describe Event, type: :model do
describe '#foo' do
subject { event.foo }
let(:event) { create(:event) }
it 'does something' do
expect(subject).to eq(true)
end
end
end
发布我的问题后找到答案:
describe Event, type: :model do
it 'calls bar' do
event = create(:event)
allow(event).to receive(:bar)
expect(event).to receive(:bar)
event.foo
end
end