如何使用RSpec should_receive忽略额外的消息?

时间:2013-12-10 18:17:28

标签: ruby rspec sinatra expectations

规格:

before do
  Logger.should_receive( :write ).with 'Log message 1'    
end

it 'works' do
  get '/'
end

Sinatra App:

get '/'
  Logger.write( 'Log message 1' )
  Logger.write( 'Log message 2' )
end

此规范因“日志消息2”而失败。如何告诉RSpec忽略任何其他消息,并仅测试预期的消息?

2 个答案:

答案 0 :(得分:7)

您需要在消息期望之前存根将接收消息的方法。

# RSpec < 3
Logger.stub(write: nil)

stub method is deprecated in RSpec 3,而是使用以下

之一
# RSpec >= 3
allow(Logger).to receive(:write).and_return(nil)  # Most appropriate in this case
allow(Logger).to receive(:write) { nil }  # Prefer block when returning something of a dynamic nature, e.g. a calculation
allow(Logger).to receive_messages(write: nil)  # Prefer hash when stubbing multiple methods at once, e.g. receive_messages(info: nil, debug: nil)

方法存根是对象(真实或测试双)的指令,用于返回响应消息的已知值。

在这种情况下,告诉Logger对象在收到nil消息时(第一次)返回值write

因此,您的before区块应如下所示

before do
  Logger.stub(write: nil)
  Logger.should_receive(:write).with('Log message 1')
end

答案 1 :(得分:2)

这个问题有点老了,但是我已经找到了自己的方式,我想我会在假设rspec-mocks v3的情况下回答它。

预先对对象进行存根,然后当您关心对象收到某条消息而不是接收该消息时,使用have_received进行断言效果很好。

receive(:...)have_received(:...)

之间的细微差别

要继续原始问题,并假设它已在rspec-mocks v3中重写,我的解决方案将是:

allow(Logger).to receive(:write)
get '/'
expect(Logger).to have_received(:write).with('Log message 1')

请注意,在调用时检查存根状态是非常重要的,而不是按照惯例检查存根状态。