Я хочу проверить влияние значения ключа 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, чтобы избежать этой проблемы?
4 ответа
Ты можешь использовать
stub_const 'ENV', ENV.to_h.merge('ADWORDS_RUN' => 'No')
Вы переопределяете / перезаписываете метод []
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
Для clim_control gem.
Вы оборачиваете свой тест вокруг блока 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
Вот как я решил эту проблему:
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» вместо «No».)
Похожие вопросы
Новые вопросы
ruby-on-rails
Ruby on Rails - это полнофункциональная платформа веб-приложений с открытым исходным кодом, написанная на Ruby. Он следует популярной модели фреймворка MVC и известен своим подходом «соглашение поверх конфигурации» при разработке приложений.