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了上面的代码能够按预期工作,但是在info
和debug
级别下,它似乎并不直接工作。 我猜是因为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
如果使用Logger
或Logging
等库,则可能必须使用output.to_<>_from_any_process
。