ruby-on-rails – 如何从Rspec功能规范测试Rails日志记录?

This question告诉我如何从RSpec模型和控制器规范测试记录器语句.不幸的是,它似乎不适用于功能规范.使用此代码:

# controller.rb
def action
  logger.info 'foobar'
end

# spec.rb
scenario 'logging should work' do
  expect(Rails.logger).to receive(:info).with('foobar')
  visit action_path
end

我收到错误:

 Failure/Error: visit action_path
   #<ActiveSupport::Logger:0x007ff45b6e5ad0> received :info with unexpected arguments
     expected: ("foobar")
          got: (no args)

test.log文件不包含foobar,因此在控制器操作有机会完成之前,测试似乎立即失败.

有没有办法在功能规范中使用这种expect(Rails.logger)语法?

最佳答案
Rails.logger.info method可以采用字符串或块.如果你正在调用块形式,那么它将给出这个“got:(no args)”输出.

例如

logger.info 'foobar'

…所有在一行上将使用字符串调用.info,但如果你这样做

logger.info
  "foobar foobar longer message so I'll put it on its own line"

分成两行没有括号,然后你实际上传递了一个块.添加一些括号……

logger.info(
  "foobar foobar longer message so I'll put it on its own line"
)

……而你又回到了一个字符串.

他故意在这个问题上猛烈抨击了几个小时之后:-)

在意识到这一点之前,我开始弄清楚如何模拟Rails.logger类.这对您或其他人来说可能是一种有用的方法.也许你是因为其他原因而调用了一个块(与功能与控制器规格有关?),或者你可能无法更改调用代码,在这种情况下……这样的事情可能是一个有用的起点:

class LoggerMock < Object
  def initialize; end

  def info(progname = nil, &block)
    mock_info(block.call)
  end
end

logger_mock = LoggerMock.new
allow(Rails).to receive(:logger).and_return(logger_mock)
expect(logger_mock).to receive(:mock_info).with('foobar')
点赞