使用类替身

class_double作为对instance_double的补充提供,区别在于它验证给定类上的方法,而不是实例方法。

此外,它还提供了一个便捷方法as_stubbed_const来用定义的替身替换具体类。有关更多详细信息,请参阅更改常量

注意:class_double也可以用于模块。我们选择坚持使用class_double术语,因为class_double验证的方法通常被称为“类方法”,而不是“模块方法”,即使是在处理模块时也是如此。

背景

假设有一个名为“lib/user.rb”的文件,其中包含

class User
  def suspend!
    ConsoleNotifier.notify("suspended as")
  end
end

假设有一个名为“lib/console_notifier.rb”的文件,其中包含

class ConsoleNotifier
  MAX_WIDTH = 80

  def self.notify(message)
    puts message
  end
end

假设有一个名为“spec/user_spec.rb”的文件,其中包含

require 'user'
require 'console_notifier'

RSpec.describe User, '#suspend!' do
  it 'notifies the console' do
    notifier = class_double("ConsoleNotifier").
      as_stubbed_const(:transfer_nested_constants => true)

    expect(notifier).to receive(:notify).with("suspended as")
    expect(ConsoleNotifier::MAX_WIDTH).to eq(80)

    user = User.new
    user.suspend!
  end
end

替换现有常量

我运行rspec spec/user_spec.rb

那么所有示例都应该通过。

ConsoleNotifier.notify重命名为send_notification

假设有一个名为“lib/console_notifier.rb”的文件,其中包含

class ConsoleNotifier
  MAX_WIDTH = 80

  def self.send_notification(message)
    puts message
  end
end

我运行rspec spec/user_spec.rb

那么输出应该包含“1 个示例,1 个失败”。

并且输出应该包含“ConsoleNotifier 类未实现类方法:”。