Я хочу проверить влияние значения ключа 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
Obromios 9 Май 2016 в 10:23

4 ответа

Лучший ответ

Ты можешь использовать

stub_const 'ENV', ENV.to_h.merge('ADWORDS_RUN' => 'No')
6
Obromios 9 Май 2016 в 22:10

Вы переопределяете / перезаписываете метод [] 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
-1
AnoE 11 Май 2016 в 10:29

Для 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
0
Kelsey Hannan 10 Окт 2019 в 22:45

Вот как я решил эту проблему:

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».)

0
Allison 12 Сен 2019 в 22:04