13
As @schillingt noted in the comments, EnvironmentVarGuard was the correct way.
from test.test_support import EnvironmentVarGuard # Python(2.7 < 3)
from test.support import EnvironmentVarGuard # Python >=3
from django.test import TestCase
class MyTestCase(TestCase):
def setUp(self):
self.env = EnvironmentVarGuard()
self.env.set('VAR', 'value')
def test_something(self):
with self.env:
# ... perform tests here ... #
pass
This correctly sets environment variables for the duration of the context object with
statement.
50
The test.support.EnvironmentVarGuard
is an internal API that might be changed from version to version with breaking (backward incompatible) changes. In fact, the entire test
package is internal use only. It was explicitly stated on the test package documentation page that it’s for internal testing of core libraries and NOT a public API. (see links below)
You should use patch.dict()
in python’s standard lib unittest.mock
. It can be used as a context manager, decorator or class decorator. See example code below copied from the official Python documentation.
import os
from unittest.mock import patch
with patch.dict('os.environ', {'newkey': 'newvalue'}):
print(os.environ['newkey']) # should print out 'newvalue'
assert 'newkey' in os.environ # should be True
assert 'newkey' not in os.environ # should be True
Update: for those who doesn’t read the documentation thoroughly and might have missed the note, read more test
package notes at
- [Django]-Django: Group by date (day, month, year)
- [Django]-How to go from django image field to PIL image and back?
- [Django]-NumPy array is not JSON serializable
18
If you are loading your environment variables in Django’s settings.py
file like this:
import os
ENV_NAME = os.environ.get('ENV_NAME', 'default')
You could use this:
from django.test import TestCase, override_settings
@override_settings(ENV_NAME="super_setting")
def test_...(self):
- [Django]-Rendering a value as text instead of field inside a Django Form
- [Django]-How to programmatically call a Django Rest Framework view within another view?
- [Django]-Django: Purpose of django.utils.functional.SimpleLazyObject?
7
Using EnvironmentVarGuard
is not a good solution as it fails in some environments and works in others. see example below.
A better solution is what was suggested by erewok that requires making use of the unittest.mock
in python3.
Assuming using unittest
from unittest.mock import patch
class TestCase(unittest.TestCase):
def setUp(self):
self.env = patch.dict('os.environ', {'hello':'world'})
def test_scenario_1(self):
with self.env:
self.assertEqual(os.environ.get('hello'), 'world')
“`
- [Django]-Import data from excel spreadsheet to django model
- [Django]-Django: Using F arguments in datetime.timedelta inside a query
- [Django]-Django : Can't import 'module'. Check that module AppConfig.name is correct
1
I use py.test
as my test runner, and it allows you to create a pytest.ini
file in which you can specify a particular settings file to use while running tests.
See documentation on this here:
http://pytest-django.readthedocs.org/en/latest/configuring_django.html#pytest-ini-settings
I recommend py.test in general as a test runner, because it supports different types of test classes and even simple functions, and it’s pretty easy to set up fixtures or other code that runs before and after tests.
- [Django]-What are the limitations of Django's ORM?
- [Django]-Capture parameters in django-rest-framework
- [Django]-Django – how to visualize signals and save overrides?
1
This article explains all, the following snippet worked for me
How to Mock Environment Variables in Python’s unittest
import os
from unittest import TestCase, mock
class SettingsTests(TestCase):
@classmethod
def setUpClass(cls):
cls.env_patcher = mock.patch.dict(os.environ, {"FROBNICATION_COLOUR": "ROUGE"})
cls.env_patcher.start()
super().setUpClass()
@classmethod
def tearDownClass(cls):
super().tearDownClass()
cls.env_patcher.stop()
def setUp(self):
super().setUp()
self.assertEqual(os.environ["FROBNICATION_COLOUR"], "ROUGE")
def test_frobnication_colour(self):
self.assertEqual(os.environ["FROBNICATION_COLOUR"], "ROUGE")
- [Django]-How to group by AND aggregate with Django
- [Django]-Tell if a Django Field is required from template
- [Django]-How to run a celery worker with Django app scalable by AWS Elastic Beanstalk?
0
Old question, but it turned up in a Google search and neither of the existing answers are suitable. If you’re using pytest, env vars can be set/restored using pytest’s monkeypatching functionality.
- [Django]-Django Framework – Is there a shutdown event that can be subscribed to?
- [Django]-Is there a way to loop over two lists simultaneously in django?
- [Django]-No handlers could be found for logger
0
Instructions all the way Mock Environment Variables in Python’s unittest
https://adamj.eu/tech/2020/10/13/how-to-mock-environment-variables-with-pythons-unittest/
- [Django]-How do I import the Django DoesNotExist exception?
- [Django]-Inline Form Validation in Django
- [Django]-Strings won't be translated in Django using format function available in Python 2.7
0
Django 4.x, you can use mock.patch.dict
to override os.environ
while testing, for e.g.:
import os
from unittest import mock
from django.test import TestCase
class ExampleTestCase(TestCase):
@mock.patch.dict(os.environ, {
"CREDENTIAL_PATH": "/example/fixtures/tests/test-credential.json"
})
def test_initialize_firebase_credential_if_needed(self):
print(f"CREDENTIAL_PATH: {os.environ.get('CREDENTIAL_PATH')}")
- [Django]-Setting the selected value on a Django forms.ChoiceField
- [Django]-Django Cache cache.set Not storing data
- [Django]-Need to convert a string to int in a django template
-1
Initially, my env variable PARTNER_CODE
was set to wow
.
I could able to change the env variable using the following:
from test.support import EnvironmentVarGuard
with EnvironmentVarGuard() as env:
env['PARTNER_CODE'] = 'sos'
Now my env variable PARTNER_CODE
says sos
.
- [Django]-Detect mobile, tablet or Desktop on Django
- [Django]-Django / Comet (Push): Least of all evils?
- [Django]-How to customize activate_url on django-allauth?