如何在 RSpec 中模拟 Ruby "require" 语句?
How can I mock a Ruby "require" statement in RSpec?
我有一个 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
(这只是输入,而不是 copy/pasted - 实际代码会掩盖问题。)
无论我尝试什么,我都无法捕获 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
建议?
因此 require
由 Kernel
定义,但 Kernel
包含在 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)
旧答案:
这是不正确的,由于 up-votes 收到,仅供后代使用。一些没有 allow
的工作方式。如果有人能解释为什么我认为它应该提高,我会很高兴。我认为这个问题与 and_return
有关,这不是预期的一部分。我的猜测是我们只测试自己收到 require
、with_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
由于我不清楚你的具体实现,因为你对问题进行了混淆处理,我无法解决你的确切问题。
我有一个 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
(这只是输入,而不是 copy/pasted - 实际代码会掩盖问题。)
无论我尝试什么,我都无法捕获 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
建议?
因此 require
由 Kernel
定义,但 Kernel
包含在 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)
旧答案:
这是不正确的,由于 up-votes 收到,仅供后代使用。一些没有 allow
的工作方式。如果有人能解释为什么我认为它应该提高,我会很高兴。我认为这个问题与 and_return
有关,这不是预期的一部分。我的猜测是我们只测试自己收到 require
、with_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
由于我不清楚你的具体实现,因为你对问题进行了混淆处理,我无法解决你的确切问题。