12

规格:

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

it 'works' do
  get '/'
end

西纳特拉应用程序:

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

由于“记录消息 2”,此规范失败。如何告诉 RSpec 忽略任何其他消息,只测试预期的消息?

4

2 回答 2

8

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

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

stub方法在 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返回值。nilwrite

所以你的before块应该是这样的

before do
  Logger.stub(write: nil)
  Logger.should_receive(:write).with('Log message 1')
end
于 2013-12-10T18:23:46.963 回答
3

这个问题有点老了,但是在这里找到了我的方式,我想我会假设 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')

请注意,将断言放在末尾很重要,因为它在调用时检查存根状态,而不是按照惯例在完成时检查。

于 2018-03-22T07:28:13.910 回答