在运行rspec for ruby时,如何更改环境变量?

yxyvkwin  于 2023-10-17  发布在  Ruby
关注(0)|答案(4)|浏览(134)

我有几个ruby脚本,用rspec测试它们。
我把我的环境放在一个env.rb文件中(目前),这样我就可以在本地访问它们,并在生产环境中把它们放在配置变量中。
但是当我运行rspec时,我需要不同的环境变量。两个用例:

  • 我运行Twilio,所以我希望能够更改用于测试凭据的SID
  • 我把东西存储在一个数据库中作为一个服务,并希望有一个单独的测试数据库
li9yvcax

li9yvcax1#

你可以

  • ENV["FOO_BAR"] = "baz"的上下文中显式设置ENV变量
  • 在初始化器中选中Rails.env.test?,以设置twilio和其他具有测试特定选项的客户端
  • 有一个文件与所有您的环境设置测试,然后使用dotenv

我个人更喜欢只在创建对象并将env var值传递给构造函数时使用ENV var,这样我就可以在不关心ENV的情况下测试对象类,并且我可以通过使用env varAssert创建来测试使用env var替换另一个对象的对象。
所以你会改变一些东西,

  1. class Client
  2. def initialize
  3. @restclient = RestClient::Resource.new(ENV["API_URL"])
  4. end
  5. end

  1. class Client
  2. def initialize(url)
  3. @restclient = RestClient::Resource.new(url)
  4. end
  5. end

然后让初始化该示例的东西传递env var的值

  1. def fetch_content
  2. client = Client.new(ENV["API_URL"])
  3. # ...
  4. end

通过这种方式,您可以测试Client类,而无需关心env变量,只需传递任何url,然后可以测试将client示例化为

  1. it "uses client" do
  2. ENV["API_URL"] = "foo.com"
  3. expect(Client).to receive(:new).with(ENV["API_URL"])
  4. subject.fetch_content
  5. end

更新env var的一个问题是,更改会在测试套件的其余部分中持续存在,如果您不希望它出现在某些测试中,则可能会导致问题,在这些情况下,您可以使用

  1. expect(ENV).to receive(:[]).with("API_URL").and_return("foo.com")
展开查看全部
k5ifujac

k5ifujac2#

由于ENV是全局状态,因此您希望在每个规格之后重置该值,以避免它在规格之间泄漏:

  1. describe 'enabled?' do
  2. around do |example|
  3. env_value_before = ENV['MIXPANEL_ENABLED']
  4. ENV['MIXPANEL_ENABLED'] = env_value
  5. example.run
  6. ENV['MIXPANEL_ENABLED'] = env_value_before
  7. end
  8. context 'when ENV not set' do
  9. let(:env_value) { nil }
  10. it 'returns true' do
  11. expect(subject.enabled?).to eq(true)
  12. end
  13. end
  14. context 'when ENV is set' do
  15. let(:env_value) { '1' }
  16. it 'returns false' do
  17. expect(subject.enabled?).to eq(false)
  18. end
  19. end
  20. end
展开查看全部
q5lcpyga

q5lcpyga3#

你可以模拟ENV来返回一个值。这是一个超级干净的一行程序,确保没有任何东西会泄漏到其他测试中:

  1. context 'when LOG_LEVEL is DEBUG' do
  2. before { allow(ENV).to receive(:[]).with('LOG_LEVEL').and_return('debug') }
  3. ...

如果你的代码只看一个ENV变量,这很好用。如果它需要其他var,而这些var对这个测试不感兴趣,你可以允许它们调用original:(虽然这开始感觉有点笨拙)

  1. context 'when LOG_LEVEL is DEBUG' do
  2. before do
  3. allow(ENV).to receive(:[]).and_call_original
  4. allow(ENV).to receive(:[]).with('LOG_LEVEL').and_return('debug')
  5. end
r3i60tvu

r3i60tvu4#

如果你经常需要在同一个上下文中存根多个环境变量,可以使用这个帮助器方法:

  1. def stub_env_variable(env_variable, new_value)
  2. unless RSpec::Mocks.space.registered?(ENV)
  3. # With the condition it allows us to call this helper multiple times for different env variables
  4. # in the same context.
  5. #
  6. # Allowing to return original ENV variables which are not yet stubbed:
  7. allow(ENV).to receive(:[]).and_call_original
  8. end
  9. allow(ENV).to receive(:[]).with(env_variable).and_return(new_value)
  10. end

它允许在相同的上下文中设置多个环境变量,但以更干净的方式,例如:

  1. before do
  2. stub_env_variable("VAR_1", 123)
  3. stub_env_variable("VAR_2", false)
  4. stub_env_variable("VAR_3", "qwerty")
  5. end

灵感来自@大卫·亨比的回答。

展开查看全部

相关问题