在我的 Gem 的 RSpec 测试中模拟 `Rails.logger`

Mocking `Rails.logger` in the RSpec tests for my Gem

我正在写一个 Ruby gem,下面是我如何创建一个新的 Logger.

的实现

我的 gem 可能会或可能不会在 Rails 内部使用,因此它会尝试使用 Rails.logger 如果存在的话。

require 'logger'

module MyLoggeer
  def logger
    @logger ||= rails_logger || Logger.new($stdout)
  end

  def rails_logger
    if defined?(::Rails) && ::Rails.respond_to?(:logger) && !::Rails.logger.nil?
      ::Rails.logger
    else
      nil
    end
  end
end

我的 gem 没有在任何地方定义 Rails 作为常量。如果我想用 RSpec 测试上面的逻辑,有没有办法让我 -

  1. 定义一个 mock Rails 对象
  2. 它是否响应了 logger 方法?

我想我可以在我的规范文件中定义一个虚拟 class,但我希望有一种方法可以轻松地模拟/存根它。

谢谢!

借助 RSpec 模拟,您可以使用 double(如替身)为任何对象创建替身。

然后使用 allow 允许替身接收消息,并使用 expect 设置方法期望。

let(:logger) do
  instance_double("Logger")
end

let(:rails) do
  double("Rails")
end

before do
  allow(rails).to receive(:logger).and_return(logger)
  stub_const("Rails", rails)
end

您也可以使用 instance doubles and class doubles to create doubles of existing classes - 这将验证您是否只调用在您加倍的 class 上实际存在的方法。

stub_const 将在示例的持续时间内存根常量的值。