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

yxyvkwin  于 12个月前  发布在  Ruby
关注(0)|答案(4)|浏览(97)

我有几个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替换另一个对象的对象。
所以你会改变一些东西,

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

class Client
  def initialize(url)
    @restclient = RestClient::Resource.new(url)
  end
end

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

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

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

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

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

expect(ENV).to receive(:[]).with("API_URL").and_return("foo.com")
k5ifujac

k5ifujac2#

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

describe 'enabled?' do
  around do |example|
    env_value_before = ENV['MIXPANEL_ENABLED']
    ENV['MIXPANEL_ENABLED'] = env_value
    example.run
    ENV['MIXPANEL_ENABLED'] = env_value_before
  end

  context 'when ENV not set' do
    let(:env_value) { nil }

    it 'returns true' do
      expect(subject.enabled?).to eq(true)
    end
  end

  context 'when ENV is set' do
    let(:env_value) { '1' }

    it 'returns false' do
      expect(subject.enabled?).to eq(false)
    end
  end
end
q5lcpyga

q5lcpyga3#

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

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

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

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

r3i60tvu4#

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

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

  allow(ENV).to receive(:[]).with(env_variable).and_return(new_value)
end

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

before do
  stub_env_variable("VAR_1", 123)
  stub_env_variable("VAR_2", false)
  stub_env_variable("VAR_3", "qwerty")
end

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

相关问题