["python","unit-testing","python-3.x","dependency-injection","mocking"]
Python mock Patch os.environ and return value

Unit testing conn() using mock: app.py import mysql.connector import os, urlparse def conn(): if "DATABASE_URL" in os.environ: url = urlparse(os.environ["DATABASE_URL"]) g.db = mysql.connector.connect( user=url.username, password=url.password, host=url.hostname, database=url.path[1:], ) else: return "Error" test.py def test_conn(self): with patch(app.mysql.connector) as mock_mysql: with patch(app.os.environ) as mock_environ: con() mock_mysql.connect.assert_callled_with("credentials") Error: Assertion mock_mysql.connect.assert_called_with is not called. which I believe it is because 'Database_url' is not in my patched os.environ and because of that test call is not made to mysql_mock.connect. Questions: What changes do I need to make this test code work? Do I also have to patch urlparse?
You can try unittest.mock.patch.dict solution. Just call conn with a dummy argument: import mysql.connector import os, urlparse from unittest import mock @mock.patch.dict(os.environ, {"DATABASE_URL": "mytemp"}, clear=True) # why need clear=True explained here https://stackoverflow.com/a/67477901/248616 # If clear is true then the dictionary will be cleared before the new values are set. def conn(mock_A): print os.environ["mytemp"] if "DATABASE_URL" in os.environ: url = urlparse(os.environ["DATABASE_URL"]) g.db = mysql.connector.connect( user=url.username, password=url.password, host=url.hostname, database=url.path[1:], ) else: return "Error" Or if you don't want to modify your original function try this solution: import os from unittest import mock def func(): print os.environ["mytemp"] def test_func(): k = mock.patch.dict(os.environ, {"mytemp": "mytemp"}) k.start() func() k.stop() test_func()