我想测试一下ENV键值对我的代码的影响。我正在使用
来解决这个问题allow(ENV).to receive(:[]).with('ADWORDS_RUN').and_return('No')
这一直有效,直到我更改了目标代码以包含访问另一个ENV密钥。目标代码现在包括以下
def not_local_machine?
!ENV['LOCAL_MACHINE']
end
现在测试在上述函数中失败并显示错误消息
Failure/Error: get 'home'
ENV received :[] with unexpected arguments
expected: ("ADWORDS_RUN")
got: ("LOCAL_MACHINE")
Please stub a default value first if message might be received with other args as well.
看来我目前的存根方法是擦除其他ENV键。如何存根ENV键以避免此问题?
答案 0 :(得分:6)
您可以使用
stub_const 'ENV', ENV.to_h.merge('ADWORDS_RUN' => 'No')
答案 1 :(得分:0)
您正在覆盖/覆盖ENV的[]
方法。原来的意思完全消失了。
查看https://github.com/rspec/rspec-mocks并查找“任意处理”一章。它包含以下示例代码:
expect(double).to receive(:msg) do |arg|
expect(arg.size).to eq 7
end
你应该能够根据自己的需要采用这种方法......(未经测试的)
dummy_env = { ADWORDS_RUN: 1, LOCAL_MACHINE: 2 }
allow(ENV).to receive(:[]) do |key|
dummy_env[key] or raise "#{key} not expected"
end
或者如果你想保留所有旧的ENV条目
env_clone = ENV.clone
allow... do|key|
dummy_env[key] or env_clone[key]
end
答案 2 :(得分:0)
这是我解决该问题的方法:
before { allow(ENV).to receive(:[]).and_call_original }
context 'ADWORDS_RUN is No' do
before { allow(ENV).to receive(:[]).with('ADWORDS_RUN').and_return('No') }
[example block]
end
(此外,我建议使用“ false”之类的东西代替“否”。)
答案 3 :(得分:0)
对于modifying ENV's in tests,Thoughtbot的climate_control宝石值得一看。
您将测试包装在ClimateControl
块周围,以控制对ENV值的临时更改。以您的示例为例:
ClimateControl.modify ADWORDS_RUN: 'No' do
expect(AdwordsTask.new.run?).to eq(false)
end
要与RSpec一起使用,可以在您的规范中定义它:
def with_modified_env(options, &block)
ClimateControl.modify(options, &block)
end
这将提供更直接的方法来修改/存根环境值:
require 'spec_helper'
describe AdwordsTask, 'name' do
it 'does not run adwords' do
with_modified_env ADWORDS_RUN: 'No' do
expect(AdwordsTask.new.run?).to eq(false)
end
end
def with_modified_env(options, &block)
ClimateControl.modify(options, &block)
end
end