【问题标题】:What is the best way to write specs for code that depends on environment variables?为依赖于环境变量的代码编写规范的最佳方法是什么?
【发布时间】:2012-03-25 13:25:15
【问题描述】:

我正在测试一些从环境变量中提取其配置的代码(在生产中由 Heroku config vars 设置,对于本地开发,我使用工头)。

用 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

【问题讨论】:

  • 我看不出你所做的有什么问题。
  • 这与 Mocha 相同:ENV.stubs(:[]).with("AWS_ACCESS_KEY_ID").returns("asdf")

标签: ruby rspec environment-variables


【解决方案1】:

你也可以存根常量:

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

或者,如果您仍然想要 ENV 的其余部分:

stub_const('ENV', ENV.to_hash.merge('AWS_ACCESS_KEY_ID' => 'asdf'))

【讨论】:

  • ENV 似乎没有 merge 方法(至少在 Ruby 1.9.3 中)。
  • 这是快速 env 存根的最佳方法,但在第二种情况下,您需要 ENV.to_hash 来保留原始 env。
  • 使哈希键双引号使它对我有用。当我有单引号的键时,它们被转换为:符号。例如::AWS_ACCESS_KEY_ID
【解决方案2】:

这样会行。

另一种方法是在代码和环境变量之间放置一层间接层,例如某种易于模拟的配置对象。

【讨论】:

  • 如果这是在 Rails 中,您已经有自己的配置对象可以添加。
  • 这是一个方便的提示。我不知道您可以如此轻松地定义自己的配置选项。只需在环境/*.rb 中执行此操作:config.my_config_value = 'value',它将以Rails.configuration.my_config_value 的形式提供。
【解决方案3】:

作为Heroku suggests,您可以使用Foreman的.env文件来存储开发环境变量。

如果您这样做,您可以使用foreman run 运行您的规范:

foreman run bundle exec rspec spec

【讨论】:

  • 如果你想在同一个环境变量中测试不同值的结果,它没有帮助。
【解决方案4】:

这个语法对我有用:

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

【讨论】:

  • 如果您使用例如fetch 访问ENV 将不起作用。
  • 添加几行用于获取:allow(ENV).to receive(:fetch).with(name).and_return(value)
【解决方案5】:

我会避免使用 ENV.stub(:[]) - 如果其他东西正在使用 ENV,例如 pry,它就不起作用(你会收到一个关于需要存根 DISABLE_PRY 的错误)。

#stub_const 效果很好,正如已经指出的那样。

【讨论】:

    【解决方案6】:

    如果您在测试期间使用dotenv 设置环境,但需要为特定测试修改环境变量,那么以下方法可能很有用。

    比存根ENV 更简单的方法是在测试期间替换环境,然后像这样恢复它:

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

    使用这样的助手:

    module EnvironmentHelper
      def with_environment(replacement_env)
        original_env = ENV.to_hash
        ENV.update(replacement_env)
    
        yield
      ensure
        ENV.replace(original_env)
      end
    end
    

    使用ensure即使测试失败也会恢复原来的环境。

    有一个方便的比较 setting & modifying environment variables during tests 的方法,包括存根 ENV,在测试之前/之后替换值,以及像 ClimateControl 这样的 gem。

    【讨论】:

      【解决方案7】:

      您可以使用https://github.com/littleowllabs/stub_env 来实现此目的。它允许您存根单个环境变量,而无需像您的解决方案建议的那样存根所有它们。

      安装gem然后写

      before :each do
        stub_env('AWS_ACCESS_KEY_ID', 'asdf')
        stub_env('AWS_SECRET_ACCESS_KEY','secret')
      end
      

      【讨论】:

        【解决方案8】:

        你想要的是dotenv gem

        正如@ciastek 所建议的,在工头下运行测试在从 CLI 运行规范时效果很好。但这并不能帮助我在 Sublime Text 2 中使用 Ruby Test 运行规范。Dotenv 完全按照你的方式,透明地完成。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-03-03
          • 2020-07-09
          • 2019-09-08
          • 1970-01-01
          • 1970-01-01
          • 2016-06-21
          • 2011-03-29
          • 2018-12-29
          相关资源
          最近更新 更多