RSpec的:如何测试Rails的记录器消息的预期?(RSpec: how to test Rail

2019-06-25 10:09发布

我想测试Rails的记录器在我的一些规格的接收消息。 我使用的日志记录的宝石 。

比方说,我有这样一个类:

class BaseWorker

  def execute
    logger.info 'Starting the worker...'
  end

end

而一个规范,如:

describe BaseWorker do

  it 'should log an info message' do
    base_worker = BaseWorker.new
    logger_mock = double('Logging::Rails').as_null_object
    Logging::Rails.stub_chain(:logger, :info).and_return(logger_mock)

    logger_mock.should_receive(:info).with('Starting the worker...')
    base_worker.execute
    Logging::Rails.unstub(:logger)
  end

end

我得到以下故障消息:

 Failure/Error: logger_mock.should_receive(:info).with('Starting worker...')
   (Double "Logging::Rails").info("Starting worker...")
       expected: 1 time
       received: 0 times

我已经尝试了几种不同的方法来获取规范通过。 这适用于例如:

class BaseWorker

  attr_accessor :log

  def initialize
    @log = logger
  end

  def execute
    @log.info 'Starting the worker...'
  end

end

describe BaseWorker do
  it 'should log an info message' do
    base_worker = BaseWorker.new
    logger_mock = double('logger')
    base_worker.log = logger_mock

    logger_mock.should_receive(:info).with('Starting the worker...')
    base_worker.execute
  end
end

但是,不必设置这样的访问的实例变量好像尾巴在这里摇狗。 (其实,我也不知道为什么拷贝记录仪@log会让它通过。)

什么是用于测试记录好的解决办法?

Answer 1:

虽然我同意你一般不希望测试记录仪,有时也可能是有用的。

我曾与市场预期的成功Rails.logger

使用RSpec的的弃用should语法:

Rails.logger.should_receive(:info).with("some message")

使用RSpec的的新expect语法:

expect(Rails.logger).to receive(:info).with("some message")

注:在控制器和模型规范,你必须把这个线记录的消息之前 。 如果你把它之后,你会得到这样的错误信息:

Failure/Error: expect(Rails.logger).to receive(:info).with("some message")
       (#<ActiveSupport::Logger:0x007f27f72136c8>).info("some message")
           expected: 1 time with arguments: ("some message")
           received: 0 times


Answer 2:

使用RSpec 3+版本

含有的单次调用实际代码Rails.logger.error

Rails.logger.error "Some useful error message"

规格代码:

expect(Rails.logger).to receive(:error).with(/error message/)

如果你想成为真正记录的错误消息,而规范的运行,然后使用下面的代码:

expect(Rails.logger).to receive(:error).with(/error message/).and_call_original

含的多个调用实际代码Rails.logger.error

Rails.logger.error "Technical Error Message"
Rails.logger.error "User-friendly Error Message"

规格代码:

expect(Rails.logger).to receive(:error).ordered
expect(Rails.logger).to receive(:error).with(/User-friendly Error /).ordered.and_call_original

此外,如果你关心的只是比较第一消息并没有任何后续消息,那么你可以使用以下

  expect(Rails.logger).to receive(:debug).with("Technical Error Message").ordered.and_call_original
  expect(Rails.logger).to receive(:debug).at_least(:once).with(instance_of(String)).ordered

注意在上述变动设定.ordered是很重要的其他预期设定启动失败。

参考文献:

http://www.relishapp.com/rspec/rspec-mocks/v/3-4/docs/setting-constraints/matching-arguments

http://www.relishapp.com/rspec/rspec-mocks/v/3-4/docs/setting-constraints/message-order



Answer 3:

如果你的目标是测试记录功能,你也可以考虑验证输出到标准流。

这将免去你的嘲讽过程和测试的消息是否会真正结束了,他们应该(STDOUT / STDERR)。

使用RSpec的输出匹配 (在3.0中引入),你可以做到以下几点:

expect { my_method }.to output("my message").to_stdout
expect { my_method }.to output("my error").to_stderr

在库如的情况下, LoggerLogging您可能必须使用output.to_<>_from_any_process



文章来源: RSpec: how to test Rails logger message expectations?