我意识到我编写测试的方式正在产生误报。
说我有这个源代码
class MyClass
def foo
end
def bar
1
end
end
foo
方法什么都不做,但是我想写一个测试,确保它在引擎盖下调用bar
(即使它没有)。此外,我希望确保直接调用bar
的结果为1
。
it "test" do
inst = MyClass.new
expect(inst).to receive(:bar).and_call_original
inst.foo
expect(inst.bar).to eq(1)
end
所以这是真的,但我希望它返回false。
我想要这一行:
expect(inst).to receive(:bar).and_call_original
到不考虑到在我的测试用例中我直接调用inst.bar
这一事实。我希望仅查看foo
方法的内部。
答案 0 :(得分:1)
您在一个测试用例中定义了2个单独的测试用例。您应该将其更改为2个单独的测试。
describe '#bar' do
it "uses #foo" do
inst = MyClass.new
allow(inst).to receive(:foo).and_call_original
inst.bar
expect(inst).to have_received(:foo)
end
it "returns 1" do
inst = MyClass.new
# if you don't need to mock it, don't do it
# allow(inst).to receive(:foo).and_call_original
expect(inst.bar).to eq(1)
end
# if you really, really wan't to do it your way, you can specify the amount of calls
it "test" do
inst = MyClass.new
allow(inst).to receive(:foo).and_call_original
inst.foo
expect(inst.bar).to eq(1)
expect(inst).to have_received(:foo).twice # or replace .twice with .at_least(2).times
end
end
答案 1 :(得分:1)
存根通常以两种方式使用:
expect_any_instance_of(MyClass).to receive(:foo)
在这种情况下它返回的内容并不是真正重要的allow_any_instance_of(MyClass).to receive(:method).and_return(fake_response)
。这是避免数据库交互和隔离测试中其他依赖项的好方法。 例如,在需要对Rails ActiveRecord模型Product
进行数据设置的测试中,该模型具有多个关联comments
:
let(:product) { Product.new }
let(:comments) { [Comment.new(text: "Foo"), Comment.new(text: "Bar")] }
before :each do
allow_any_instnace_of(Product).to recieve(:comments).and_return(comments)
现在,当您拨打it
时,在任何product.comments
区块中,您将获得一系列评论,您可以在测试中使用这些评论而不必靠近您的数据库,从而使测试顺序的速度更快
当您使用存根来检查方法是否被调用时,关键是在执行调用方法的opreation之前声明期望值。例如:
expect_any_instance_of(Foo).to recieve(:bar).exactly(1).times.with('hello')
Foo.new.bar('hello') # will return true