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

Ros*_*son 0 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
Run Code Online (Sandbox Code Playgroud)

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

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

expect(Kernel).to receive(:require).with(file).and_return(true)
Run Code Online (Sandbox Code Playgroud)

甚至:

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)
Run Code Online (Sandbox Code Playgroud)

但似乎没有任何勾结 require

有什么建议吗?

eng*_*nky 6

So require由定义KernelKernel包含在其中,Object因此当您require在此上下文中调用时,不一定Kernel是正在处理该语句的模块。

更新资料

我不确定这是否能解决您的问题,但不会出现以下异常行为:

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)
Run Code Online (Sandbox Code Playgroud)

工作实例

老答案:

这是不正确的,并且由于收到的过高票数仅在后代存在。一些没有的工作原理allow。如果有人可以解释我为什么应该提出来,为什么会喜欢。我认为这个问题与and_return不属于期望的地方有关。我的猜测是,我们仅测试自己收到的requirewith_file并且该and_return部分只是消息传输(因此是我更新的答案)

您仍然可以像这样存根:

file = 'non-existent-file.rb'
allow_any_instance_of(Kernel).to receive(:require).with(file).and_return(true)
expect(self).to receive(:require).with(file).and_return(true)
require file
Run Code Online (Sandbox Code Playgroud)

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