Как лучше всего писать спецификации для кода, зависящего от переменных среды?

Я тестирую некоторый код, который извлекает свою конфигурацию из переменных среды (установленных конфигурационными переменными Heroku в производстве, для локальной разработки я использую Foreman).

Как лучше всего протестировать такой код с помощью RSpec?

Я придумал это:

before :each do
    ENV.stub(:[]).with("AWS_ACCESS_KEY_ID").and_return("asdf")
    ENV.stub(:[]).with("AWS_SECRET_ACCESS_KEY").and_return("secret")
end

Если вам не нужно тестировать разные значения переменных среды, я думаю, вы могли бы вместо этого установить их в spec_helper.


person Luke Francl    schedule 08.03.2012    source источник
comment
Я не вижу ничего плохого в том, что ты делаешь.   -  person Andrew Marshall    schedule 08.03.2012
comment
То же самое работает и с Mocha: ENV.stubs(:[]).with("AWS_ACCESS_KEY_ID").returns("asdf")   -  person jeradg    schedule 03.10.2014


Ответы (8)


Это сработает.

Другим способом было бы поместить уровень косвенности между вашим кодом и переменными среды, например, какой-то объект конфигурации, который легко имитировать.

person nicholaides    schedule 08.03.2012
comment
Если это в Rails, у вас уже есть собственный объект конфигурации, который вы можете добавить, если хотите. - person Andrew Marshall; 08.03.2012
comment
Это удобный совет. Я не знал, что вы можете так легко определить свои собственные параметры конфигурации. Просто сделайте это в environments/*.rb: config.my_config_value = 'value' и он будет доступен как Rails.configuration.my_config_value. - person Luke Francl; 20.03.2012

Вы также можете заглушить константу:

stub_const('ENV', {'AWS_ACCESS_KEY_ID' => 'asdf'})

Или, если вам все еще нужна остальная часть ENV:

stub_const('ENV', ENV.to_hash.merge('AWS_ACCESS_KEY_ID' => 'asdf'))
person iGEL    schedule 13.11.2013
comment
ENV не имеет метода merge (по крайней мере, в Ruby 1.9.3). - person David Tuite; 27.08.2014
comment
Это лучший подход для быстрой заглушки окружения, но во втором случае вам нужно ENV.to_hash, чтобы сохранить исходное окружение. - person Fabio; 17.11.2014
comment
Создание двойных кавычек хеш-ключей заставило меня работать. Когда у меня были ключи с одинарными кавычками, они были преобразованы в: символы. Пример: :AWS_ACCESS_KEY_ID - person Pratik Khadloya; 15.09.2015

Как предлагает Heroku, вы можете использовать файл Foreman .env для хранения переменных среды для разработки.

Если вы это сделаете, вы можете использовать foreman run для запуска своих спецификаций:

foreman run bundle exec rspec spec
person ciastek    schedule 12.06.2012
comment
Это не поможет, если вы хотите проверить результаты разных значений в одной и той же переменной env. - person Tadas Sasnauskas; 20.07.2015

Этот синтаксис работает для меня:

module SetEnvVariable

  def set_env_var(name, value)
   # Old Syntax
   # ENV.stub(:[])
   # ENV.stub(:[]).with(name).and_return(value)

   allow(ENV).to receive(:[]) # stub a default value first if message might be received with other args as well.
   allow(ENV).to receive(:[]).with(name).and_return(value)
  end

end
person aldrien.h    schedule 06.09.2018
comment
не будет работать, если вы используете, например, fetch для доступа ENV. - person hoffmanc; 04.02.2019

Я бы избегал ENV.stub(:[]) - это не работает, если другие вещи используют ENV, например pry (вы получите сообщение об ошибке о необходимости заглушки DISABLE_PRY).

#stub_const работает хорошо, как уже указывалось.

person Calvin    schedule 26.02.2014

Для этого вы можете использовать https://github.com/littleowllabs/stub_env. Это позволяет вам заглушить отдельные переменные среды, не заглушая их все, как было предложено вашим решением.

Установите гем, затем напишите

before :each do
  stub_env('AWS_ACCESS_KEY_ID', 'asdf')
  stub_env('AWS_SECRET_ACCESS_KEY','secret')
end
person Liam Bennett    schedule 05.11.2014

Если вы используете dotenv для настройки среды во время тестов, но вам нужно изменить переменную env для конкретного теста может быть полезен следующий подход.

Более простой метод, чем заглушка ENV, состоит в том, чтобы заменить среду на время теста, а затем восстановить ее после этого следующим образом:

with_environment("FOO" => "baz") do
  puts ENV.fetch("FOO")
end

Используя такой помощник (из Homebrew источник):

module Test
  module Helper
    module Env
      def with_environment(partial_env)
        old = ENV.to_hash
        ENV.update partial_env
        begin
          yield
        ensure
          ENV.replace old
        end
      end
    end
  end
end

При использовании ensure исходная среда восстанавливается, даже если тест не пройден.

Это удобное сравнение методов для установки и изменения переменных среды во время тестов, включая заглушки ENV, заменяющие значения до/после теста, и такие жемчужины, как ClimateControl.

person odlp    schedule 04.01.2017

Вам нужен гем dotenv.

Как предполагает @ciastek, запуск тестов под руководством мастера отлично работает при запуске спецификаций из CLI. Но это не помогает мне запускать спецификации с Ruby Test в Sublime Text 2. Dotenv делает именно то, что вы, прозрачно.

person Tim Scott    schedule 05.06.2013