Search code examples
ruby-on-railsrubyunit-testingmockingminitest

Properly mocking environment variables with minitest?


What's the right way to mock environment variables when writing unit tests using minitest for Ruby on Rails?

So I'm coming from Python where the standard way is to use a decorator like this:

@mock.patch.dict(os.environ, {'mocked_key': 'mocked_result'}

I'm a little surprised I've been unable to find anything similar in minitest when searching the documentation and Stack Overflow.

Any recommendations for the best approach to do this would be much appreciated!


Solution

  • You can set and unset environment variables using a method, for example:

    # in test_helper.rb (for example)
    def mock_env(partial_env_hash)
      old = ENV.to_hash
      ENV.update partial_env_hash
      begin
        yield
      ensure
        ENV.replace old
      end
    end
    
    # usage
    mock_env('MY_ENV_VAR' => 'Hello') do
      assert something?
    end
    

    You can alternatively use the climate_control gem to manage environment variables:

    ClimateControl.modify CONFIRMATION_INSTRUCTIONS_BCC: 'confirmation_bcc@example.com' do
      sign_up_as 'john@example.com'
    
      confirm_account_for_email 'john@example.com'
    
      expect(current_email).to bcc_to('confirmation_bcc@example.com')
    end
    

    There's also a decent article called How environment variables make your Ruby test suite flaky that goes into some more detail about how to set and unset environment variables during tests if you'd like to read about some more options.