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

我正在测试一些从环境变量中提取配置的代码(在生产环境中由 Heroku config vars 设置,对于本地开发,我使用 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中设置它们。

28833 次浏览

这样也行。

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

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

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

foreman run bundle exec rspec spec

你想要的是 Dotenv gem

正如@ciastek 建议的那样,在 Foreman 下运行测试,在运行 CLI 的规范时效果非常好。但是这并不能帮助我在 SublimeText2中运行 Ruby 测试的规格说明。Dotenv 显然和你一样。

您还可以存根常数:

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

或者,如果你还想要 ENV 剩下的部分:

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

我会避免 ENV.stub(:[])-它不工作,如果其他事情是使用 ENV如撬(你会得到一个错误,需要存根 DISABLE_PRY)。

#stub_const works well as already pointed out.

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

Install the gem then write

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

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

一个比使 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,即使测试失败,也可以恢复原始环境。

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

这种语法对我很有用:

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