RSpec:如何测试方法是否被调用?


112

在编写RSpec测试时,我发现自己写了很多类似这样的代码,以确保在测试执行过程中调用了一个方法(为了论证,我们只能说我不能真正询问状态调用后对象的名称,因为该方法执行的操作不容易看到的效果)。

describe "#foo"
  it "should call 'bar' with appropriate arguments" do
    called_bar = false
    subject.stub(:bar).with("an argument I want") { called_bar = true }
    subject.foo
    expect(called_bar).to be_true
  end
end

我想知道的是:是否有比这更好的语法?我是否缺少一些时髦的RSpec令人敬畏的东西,它将上面的代码减少到几行?should_receive听起来应该这样做,但进一步阅读听起来并不完全是这样。



@Peter Alfvin OP正在要求上提供语法should_receive,因此我认为该问题会有所帮助。
kddeisz 2014年

Answers:


141
it "should call 'bar' with appropriate arguments" do
  expect(subject).to receive(:bar).with("an argument I want")
  subject.foo
end

1
抱歉,在此示例中,我不理解这种“ to .. receive(:bar)”格式如何检查“ named_bar”的值。你能跟我解释一下吗?
ecoding5 2015年

2
@ ecoding5号 不需要,也不应该检查called_bar。那只是确保该方法被调用的标志,但是expect(...).to receive(...)您已经在讨论它了。更清晰和语义
wacko 2015年

@wacko哦,知道了,谢谢您的清理。我不是第一次见到它。
ecoding5


37

下面应该工作

describe "#foo"
  it "should call 'bar' with appropriate arguments" do
     subject.stub(:bar)
     subject.foo
     expect(subject).to have_received(:bar).with("Invalid number of arguments")
  end
end

文档:https : //github.com/rspec/rspec-mocks#expecting-arguments


谢谢-我收到了“ NoMethodError” has_received吗?-认为这可能与rspec versoins有关。我找到了另一个对我
有用的

@MikeyHogarth这个答案是暗示的have_received(“间谍”方法之后),不是has_received,这不是我所知道的任何RSpec版本的一部分。
彼得·阿尔夫文

2

为了完全符合RSpec〜> 3.1语法和rubocop-rspecrule的默认选项RSpec/MessageSpies,可以使用以下方法spy

消息期望在调用被测代码之前,首先将示例的期望放在首位。许多开发人员更喜欢使用“排列-动作-断言”(或“ never-then-then-then”)模式进行结构化测试。间谍是测试替身的另一种类型,可以通过使用Have_received允许您期望事实结束后已收到消息来支持这种模式。

# arrange.
invitation = spy('invitation')

# act.
invitation.deliver("foo@example.com")

# assert.
expect(invitation).to have_received(:deliver).with("foo@example.com")

如果您不使用rubocop-rspec或使用非默认选项。您当然可以使用带有期望的RSpec 3默认值。

dbl = double("Some Collaborator")
expect(dbl).to receive(:foo).with("foo@example.com")
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.