间谍
消息期望 将示例的期望放在开头,在你调用被测代码之前。许多开发人员更喜欢使用安排-行动-断言(或给定-何时-然后)模式来构建测试。间谍是一种支持这种模式的备选测试替身类型,它允许你使用 `have_received` 在事后期望收到一条消息。
你可以使用任何测试替身(或部分替身)作为间谍,但替身必须设置为监视你关心的消息。间谍会自动监视所有消息,或者你可以 允许一条消息 来监视它。
have_received
支持与普通消息期望相同的流畅接口,用于 设置约束。
注意:这里显示的 `have_received` API 仅适用于使用 rspec-expectations 的情况。注意:当传递的参数在间谍记录接收的消息后被更改时,`have_received(...).with(...)` 无法正常工作。
使用间谍
给定 一个名为“spy_spec.rb”的文件,其中包含
RSpec.describe "have_received" do
it "passes when the message has been received" do
invitation = spy('invitation')
invitation.deliver
expect(invitation).to have_received(:deliver)
end
end
当 我运行 `rspec spy_spec.rb` 时
那么 这些示例都应该通过。
监视部分替身上的方法
给定 一个名为“partial_double_spy_spec.rb”的文件,其中包含
class Invitation
def self.deliver; end
end
RSpec.describe "have_received" do
it "passes when the expectation is met" do
allow(Invitation).to receive(:deliver)
Invitation.deliver
expect(Invitation).to have_received(:deliver)
end
end
当 我运行 `rspec partial_double_spy_spec.rb` 时
那么 这些示例都应该通过。
消息未收到时的失败
给定 一个名为“failure_spec.rb”的文件,其中包含
class Invitation
def self.deliver; end
end
RSpec.describe "failure when the message has not been received" do
example "for a spy" do
invitation = spy('invitation')
expect(invitation).to have_received(:deliver)
end
example "for a partial double" do
allow(Invitation).to receive(:deliver)
expect(Invitation).to have_received(:deliver)
end
end
当 我运行 `rspec failure_spec.rb --order defined` 时
那么 它应该失败,并显示以下信息
1) failure when the message has not been received for a spy
Failure/Error: expect(invitation).to have_received(:deliver)
(Double "invitation").deliver(*(any args))
expected: 1 time with any arguments
received: 0 times with any arguments
并且 它应该失败,并显示以下信息
2) failure when the message has not been received for a partial double
Failure/Error: expect(Invitation).to have_received(:deliver)
(Invitation (class)).deliver(*(any args))
expected: 1 time with any arguments
received: 0 times with any arguments
使用流畅接口设置约束
给定 一个名为“setting_constraints_spec.rb”的文件,其中包含
RSpec.describe "An invitation" do
let(:invitation) { spy("invitation") }
before do
invitation.deliver("foo@example.com")
invitation.deliver("bar@example.com")
end
it "passes when a count constraint is satisfied" do
expect(invitation).to have_received(:deliver).twice
end
it "passes when an order constraint is satisfied" do
expect(invitation).to have_received(:deliver).with("foo@example.com").ordered
expect(invitation).to have_received(:deliver).with("bar@example.com").ordered
end
it "fails when a count constraint is not satisfied" do
expect(invitation).to have_received(:deliver).at_least(3).times
end
it "fails when an order constraint is not satisfied" do
expect(invitation).to have_received(:deliver).with("bar@example.com").ordered
expect(invitation).to have_received(:deliver).with("foo@example.com").ordered
end
end
当 我运行 `rspec setting_constraints_spec.rb --order defined` 时
那么 它应该失败,并显示以下输出
4 个示例,2 个失败 |
1) 当计数约束不满足时,邀请失败 |
Failure/Error: expect(invitation).to have_received(:deliver).at_least(3).times |
(Double “invitation”).deliver(*(any args)) |
预期:至少 3 次,任何参数 |
收到:2 次,任何参数 |
2) 当顺序约束不满足时,邀请失败 |
Failure/Error: expect(invitation).to have_received(:deliver).with(“foo@example.com”).ordered |
# |