如何在RSpec中模拟Ruby的“ require”语句?

时间:2019-06-07 18:59:28

标签: ruby rspec thor

我有一个Ruby cli程序,可以选择通过require加载用户指定的文件。我想通过RSpec对该功能进行单元测试。显而易见的事情是模拟需求并验证它是否已发生。像这样:

context 'with the --require option' do
  let(:file) { "test_require.rb" }
  let(:args) { ["--require", "#{file}"] }
  it "loads the specified file"
    expect(...something...).to receive(:require).with(file).and_return(true)
    command.start(args)
  end
end

(只是输入,而不是复制/粘贴-实际的代码会使问题难以理解。)

无论我尝试什么,即使发生require,我也无法捕获它(它会引发LoadError,因此我可以看到它)。我尝试了各种方法,包括最明显的方法:

expect(Kernel).to receive(:require).with(file).and_return(true)

甚至:

let(:kernel_class) { class_double('Kernel') }
kernel_class.as_stubbed_const
allow(Kernel).to receive(:require).and_call_original
allow(Kernel).to receive(:require).with(file).and_return(true)

但似乎没有任何东西挂在require

建议?

1 个答案:

答案 0 :(得分:6)

因此requireKernel定义,但是Kernel包含在Object中,因此当您在此上下文中调用require时,不一定{ 1}}模块正在处理该语句。

更新

我不确定这是否能完全解决您的问题,但不会受到以下所示奇怪行为的困扰:

Kernel

Working Example

老答案:

这是不正确的,由于收到的赞成票,仅用于后代。一些没有file = 'non-existent-file' allow(self).to receive(:require).with(file).and_return(true) expect(self).to receive(:require).with(file) expect(require file).to eq(true) 的工作方式。如果有人可以解释我为什么应该提出来,为什么会喜欢。我认为该问题与allow有关,这不是预期的一部分。我的猜测是,我们仅测试自己收到的and_returnrequire,并且with_file部分只是消息传输(因此是我更新的答案)

您仍然可以像这样存根:

and_return

由于我对您的确切实现方式尚不清楚,因为您对这个问题感到困惑,所以我无法解决您的确切问题。