为依赖于环境变量的代码编写规范的最佳方法是什么?

Luk*_*ncl 54 ruby rspec environment-variables

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

使用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
Run Code Online (Sandbox Code Playgroud)

如果您不需要测试环境变量的不同值,我猜您可以设置它们spec_helper.

iGE*_*GEL 60

你也可以存根常量:

stub_const('ENV', {'AWS_ACCESS_KEY_ID' => 'asdf'})
Run Code Online (Sandbox Code Playgroud)

或者,如果你还想要ENV的其余部分:

stub_const('ENV', ENV.to_hash.merge('AWS_ACCESS_KEY_ID' => 'asdf'))
Run Code Online (Sandbox Code Playgroud)

  • `ENV`似乎没有`merge`方法(至少在Ruby 1.9.3中). (3认同)

nic*_*des 22

那会有用.

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

  • 如果这是在Rails中你已经拥有自己的配置对象,如果你想要添加. (2认同)
  • 这是一个方便的提示.我不知道你可以这么容易地定义自己的配置选项.只需在环境/*.rb:`config.my_config_value ='value'`中执行此操作,它将作为`Rails.configuration.my_config_value`提供. (2认同)

odl*_*dlp 8

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

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

with_environment("FOO" => "baz") do
  puts ENV.fetch("FOO")
end
Run Code Online (Sandbox Code Playgroud)

使用这样的助手:

module EnvironmentHelper
  def with_environment(replacement_env)
    original_env = ENV.to_hash
    ENV.update(replacement_env)

    yield
  ensure
    ENV.replace(original_env)
  end
end
Run Code Online (Sandbox Code Playgroud)

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

有一个在测试期间设置和修改环境变量的方法的方便比较,包括存根ENV、在测试之前/之后替换值以及像 ClimateControl 这样的宝石。


cia*_*tek 7

正如Heroku建议的那样,您可以使用Foreman的.env文件存储环境变量以进行开发.

如果你这样做,你可以foreman run用来运行你的规格:

foreman run bundle exec rspec spec
Run Code Online (Sandbox Code Playgroud)

  • 如果要在同一个env变量中测试不同值的结果,则无效. (5认同)

Cal*_*vin 5

我会避免- 如果使用其他东西(例如 pry ),ENV.stub(:[])它不起作用(您会收到有关需要存根的错误)。ENVDISABLE_PRY

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


ald*_*n.h 5

这种语法对我有用:

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
Run Code Online (Sandbox Code Playgroud)