RSpec:如何testingRails日志消息的期望?

我正在尝试testingRailslogging器在我的一些规范中接收消息。 我正在使用Logging的gem 。

假设我有这样的课程:

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 

但是必须设置一个可访问的实例variables,就像尾巴在这里摇摆狗。 (实际上,我甚至不知道为什么将logging器复制到@log会使其通过。)

什么是testing日志logging的好方法?

虽然我同意你通常不想testinglogging器,但有时候它可能是有用的。

我对Rails.logger期望已经取得了成功。

使用RSpec的弃用should语法:

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

使用RSpec的新的expect语法:

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

注意:在控制器和模型规格中,必须在消息logging之前放置此行。 如果你把它放在后面,你会得到这样的错误信息:

 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 

RSpec 3+版本

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

 Rails.logger.error "Some useful error message" 

规格代码:

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

如果您希望在运行规范时实际logging错误消息,请使用以下代码:

 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 

注意在上面的变化设置。 .ordered是重要的其他预期设置开始失败。

在Rails上下文中,我已经validation了上面的代码能够按预期工作,但是在infodebug级别下,它似乎并不直接工作。 我猜是因为Rails内部使用debugging和信息级别,这可能会导致错误

 (#<ActiveSupport::Logger:0x00000006c55778>).info(*(any args)) expected: 1 time with any arguments received: 4 times with any arguments 

参考文献:

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

如果您的目标是testing日志loggingfunction,您也可以考虑validation输出到标准stream。

这将使您嘲笑进程,并testing消息是否会实际上结束在他们应该(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