unittest.mock.Mock
Create a Mock object
[1]:
from unittest import mock
m = mock.Mock()
## Define Mock object behavior
Set a default return value
[2]:
m.return_value = 42
m()
[2]:
42
Assign different return values for successive calls
side_effect must be of type list. Each time the mocked method is then called, the next value in the list is returned. If the side_effect list has no more values to return, the next call will fail with a StopIteration error.
The return_value is like a constant side_effect, which always returns the same value.
Have a Mock return string values when called
[3]:
m.side_effect = ['foo', 'bar', 'baz']
print(m())
print(m())
print(m())
foo
bar
baz
Have a Mock returns a new Mock for each function call
[4]:
number = 10
m = mock.Mock()
m.get_mock.side_effect = [mock.Mock() for _ in range(number)]
print(m.get_mock())
print(m.get_mock())
# may continue up to 'number'-times
<Mock id='4444113184'>
<Mock id='4442458784'>
Check number of calls on Mock object
Check whether mock object has been called at least once
[5]:
m = mock.Mock()
m()
m.assert_called()
Returns None, if called, otherwise raises AssertionError
Check whether mock object has been called exactly once
[6]:
m = mock.Mock()
try:
m.assert_called_once()
except AssertionError:
print("No, I wasn't called (yet)")
m()
if not m.assert_called_once():
print("Yeah, now I was called")
No, I wasn't called (yet)
Yeah, now I was called
Get number of calls to mock object
[7]:
m = mock.Mock()
m()
m()
m.call_count
[7]:
2
Get Mock call arguments
Get call arguments from most recent Mock call
[8]:
m = mock.Mock()
m(1, foo='bar')
m.call_args
[8]:
call(1, foo='bar')
If mock object hasn’t been called yet, None is returned.
Get call arguments of all previous Mock calls
[9]:
m = mock.Mock()
m()
m(1, foo='bar')
m(4, baz='bar2')
m.call_args_list
[9]:
[call(), call(1, foo='bar'), call(4, baz='bar2')]
Reset previous Mock calls (won’t change mock configuration)
[10]:
m = mock.Mock()
m()
m(1, foo='bar')
m(4, baz='bar2')
m.reset_mock()
m.call_args_list
[10]:
[]
unittest.mock.patch
Patch an import module
unittest.mock is able to patch imports in the module under test using the patch function.
patch will intercept import statements identified by a string and return a Mock instance you can preconfigure using the techniques from unittest.Mock (see above).
Module under test (work.py):
[11]:
def work_on():
path = os.getcwd()
print(f'Working on {path}')
return path
The project module imports os and uses its getcwd() method , which we want to mock in our test.
Patch using a context manager (with statement)
When using the context manager patch, the patch ends when the with statement ends.
[12]:
import unittest
from unittest import TestCase
class TestWorkMockingModule(TestCase):
def test_using_context_manager(self):
with mock.patch('work.os') as mocked_os:
work_on()
mocked_os.getcwd.assert_called_once()
unittest.main(argv=[''], verbosity=2, exit=False)
test_using_context_manager (__main__.TestWorkMockingModule.test_using_context_manager) ... ok
----------------------------------------------------------------------
Ran 1 test in 0.002s
OK
Working on <MagicMock name='os.getcwd()' id='4448422176'>
[12]:
<unittest.main.TestProgram at 0x108f095e0>
We specifically patch the work.os module, not os, as this would patch os for all modules, not just for work.py.
The test module imports the project module’s method
work_on()At the beginning of the test, the
work.osmodule (which is theosmodule in ourwork.pymodule) is patched with a MagickMock object (here calledmocked_os)When the
work_on()method is called afterward, thatMagicMockobject is called instead of the original module (os) - as no return value is definedwork_on()returns another MagicMock object - as we are not testing the correctness of the return value here, only checking if themocked_osexecuted thegetcwd()method, we do not care about the return value
The as statement in the decorator is optional. You may as well not mock the entire work.os module, but rather define a return value for the single function, that is called (getcwd()):
[13]:
from unittest import TestCase, main
class TestWorkMockingModule(TestCase):
def test_using_return_value(self):
with mock.patch('work.os.getcwd', return_value='testing'):
assert work_on() == 'testing'
main(argv=[''], verbosity=2, exit=False)
test_using_return_value (__main__.TestWorkMockingModule.test_using_return_value) ... ok
----------------------------------------------------------------------
Ran 1 test in 0.002s
OK
Working on testing
[13]:
<unittest.main.TestProgram at 0x109237710>
Patch using the decorator (@patch)
To test project classes that interact with other project classes in isolation, the other project classes must be mocked (in order to determine test failure to a specific class and method, not by any of its dependency classes).
Example:
[14]:
from unittest import TestCase, mock, main
from source.reference.python.cheat_sheets._file.work import work_on
class TestWorkMockingModule(TestCase):
@mock.patch('work.os')
def test_using_decorator(self, mocked_os):
work_on()
mocked_os.getcwd.assert_called_once()
main(argv=[''], verbosity=2, exit=False)
test_using_decorator (__main__.TestWorkMockingModule.test_using_decorator) ... ok
----------------------------------------------------------------------
Ran 1 test in 0.002s
OK
Working on <MagicMock name='os.getcwd()' id='4448619744'>
[14]:
<unittest.main.TestProgram at 0x1092915b0>
Here the work.os module is replaced with a MagicMock object.
Patching classes
To test project classes that interact with other project classes in isolation, the other project classes must be mocked (in order to determine test failure to a specific class and method, not by any of its dependency classes).
Example:
Project module (worker.py)
In this module, the Worker class needs to be tested for these two things:
the
WorkercallsHelperwithdbthe
Workerreturns the expected path supplied byHelper
[15]:
class Helper:
def __init__(self, path):
self.path = path
def get_path(self):
base_path = os.getcwd()
return os.path.join(base_path, self.path)
class Worker:
def __init__(self):
self.helper = Helper('db')
def work(self):
path = self.helper.get_path()
print(f'Working on {path}')
return path
Test module (test_worker.py)
Patch entire class
To test this, the Worker needs to be isolated from Helper, so that failures can be associated with the Worker class only.
Consequently, the entire Helper class must be patched:
```python from unittest import TestCase, mock from worker import Worker
[16]:
from unittest import TestCase, main
class TestWorkerModule(TestCase):
def test_patching_class(self):
with mock.patch('worker.Helper') as MockHelper:
MockHelper.return_value.get_path.return_value = 'testing'
worker = Worker()
MockHelper.assert_called_once_with('db')
self.assertEqual(worker.work(), 'testing')
main(argv=[''], verbosity=2, exit=False)
test_using_decorator (__main__.TestWorkMockingModule.test_using_decorator) ... ok
test_patching_class (__main__.TestWorkerModule.test_patching_class) ... ok
----------------------------------------------------------------------
Ran 2 tests in 0.003s
OK
Working on <MagicMock name='os.getcwd()' id='4447399248'>
Working on testing
[16]:
<unittest.main.TestProgram at 0x1091a6e40>
Note the double return_value in the example, simply using MockHelper.get_path.return_value would not work since in the code we call get_path on an instance, not the class itself.
Alternatively, we can preconfigure the MockHelper instance and assign it as the return value of the worker.Helper call. Below, shown for both the context manager and the decorator way:
[18]:
from unittest import TestCase, mock, main
class TestWorkerModule(TestCase):
mockHelperInstance = mock.MagicMock()
mockHelperInstance.get_path.return_value = 'testing'
# using patch context manager
def test_patch_class_context_manager(self):
with mock.patch('worker.Helper',
return_value=self.mockHelperInstance) as MockHelper:
worker = Worker()
MockHelper.assert_called_once_with('db')
self.assertEqual(worker.work(), 'testing')
# using patch class decorator
@mock.patch('worker.Helper', return_value=mockHelperInstance)
def test_patch_class_decorator(self, mock_helper):
worker = Worker()
mock_helper.assert_called_once_with('db')
self.assertEqual(worker.work(), 'testing')
main(argv=[''], verbosity=2, exit=False)
test_using_decorator (__main__.TestWorkMockingModule.test_using_decorator) ... ok
test_patch_class_context_manager (__main__.TestWorkerModule.test_patch_class_context_manager) ... ok
test_patch_class_decorator (__main__.TestWorkerModule.test_patch_class_decorator) ... ok
----------------------------------------------------------------------
Ran 3 tests in 0.005s
OK
Working on <MagicMock name='os.getcwd()' id='4448099488'>
Working on testing
Working on testing
[18]:
<unittest.main.TestProgram at 0x109289550>
Important
It is important to distinguish between mocking a class and mocking the instance of a class. Sometimes, it is necessary to mock the entire class, sometimes it might be sufficient to mock only an instance from that class.
Mocking the entire class allows for
* checking, in what way that class has been initialized
* instantiating multiple instances from it, which return a Mock object and
raises the call count
For the above worker.py module, both these tests pass:
[19]:
from unittest import TestCase, mock, main
mockHelper = mock.MagicMock()
class TestWorkerModule(TestCase):
def setUp(self):
mockHelper.reset_mock()
self.mock_helper_instance = mockHelper.return_value
@mock.patch('worker.Helper', new=mockHelper)
def test_initialization(self):
Worker()
mockHelper.assert_called_once_with('db')
@mock.patch('worker.Helper', new=mockHelper)
def test_get_path(self):
self.mock_helper_instance.get_path.return_value = 'testing'
worker = Worker()
self.assertEqual(worker.work(), 'testing')
main(argv=[''], verbosity=2, exit=False)
test_using_decorator (__main__.TestWorkMockingModule.test_using_decorator) ... ok
test_get_path (__main__.TestWorkerModule.test_get_path) ... ok
test_initialization (__main__.TestWorkerModule.test_initialization) ... ok
----------------------------------------------------------------------
Ran 3 tests in 0.005s
OK
Working on <MagicMock name='os.getcwd()' id='4448654336'>
Working on testing
[19]:
<unittest.main.TestProgram at 0x109289220>
Speccing
The danger with mocks is that a Mock object returns a new MagicMock object to basically every attribute or method it is queried for, no matter if that attribute or method actually exists. If the mocked class changes signatures or an attribute, the Mockobject will still return the requested “thing” as another Mock, simply said
The Mock does not know about the object it is mocking.
To prevent this speccing can be added to a Mock, which makes it behave as the object being mocked. The easiest to use is autospec=True option.
Example:
Assuming the Helper class changed its get_path() method to get_folder(), but the call is not changed in the Worker class:
[ ]:
import os
class Helper:
def __init__(self, path):
self.path = path
def get_folder(self):
base_path = os.getcwd()
return os.path.join(base_path, self.path)
class Worker:
def __init__(self):
self.helper = Helper('db')
def work(self):
path = self.helper.get_path()
print(f'Working on {path}')
return path
When running the previous test without the speccing option, this would pass, as we mock the get_path method for the Mock instance although the original class does not contain this method anymore.
But with the autospec=True method, the Mockget_path() method, the Mock object checks for consistence with the original object. So
[25]:
from unittest import TestCase, mock, main
mockHelper = mock.MagicMock()
class TestWorkerModuleRaisesError(TestCase):
@mock.patch('worker.Helper', new=mockHelper, autospec=True)
def test_get_path(self):
self.mock_helper_instance.get_path.return_value = 'testing'
worker = Worker()
self.assertEqual(worker.work(), 'testing')
main(argv=[''], verbosity=0, exit=False)
======================================================================
ERROR: test_get_path (__main__.TestWorkerModuleRaisesError.test_get_path)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/local/Cellar/python@3.12/3.12.5/Frameworks/Python.framework/Versions/3.12/lib/python3.12/unittest/mock.py", line 1390, in patched
with self.decoration_helper(patched,
File "/usr/local/Cellar/python@3.12/3.12.5/Frameworks/Python.framework/Versions/3.12/lib/python3.12/contextlib.py", line 137, in __enter__
return next(self.gen)
^^^^^^^^^^^^^^
File "/usr/local/Cellar/python@3.12/3.12.5/Frameworks/Python.framework/Versions/3.12/lib/python3.12/unittest/mock.py", line 1372, in decoration_helper
arg = exit_stack.enter_context(patching)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/Cellar/python@3.12/3.12.5/Frameworks/Python.framework/Versions/3.12/lib/python3.12/contextlib.py", line 526, in enter_context
result = _enter(cm)
^^^^^^^^^^
File "/usr/local/Cellar/python@3.12/3.12.5/Frameworks/Python.framework/Versions/3.12/lib/python3.12/unittest/mock.py", line 1539, in __enter__
raise TypeError(
TypeError: autospec creates the mock for you. Can't specify autospec and new.
======================================================================
FAIL: test_initialization (__main__.TestWorkerModule.test_initialization)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/local/Cellar/python@3.12/3.12.5/Frameworks/Python.framework/Versions/3.12/lib/python3.12/unittest/mock.py", line 1393, in patched
return func(*newargs, **newkeywargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/var/folders/fr/qctyd7d96dn4qrkwypwgr1pr0000gn/T/ipykernel_8439/255302047.py", line 16, in test_initialization
mockHelper.assert_called_once_with('db')
File "/usr/local/Cellar/python@3.12/3.12.5/Frameworks/Python.framework/Versions/3.12/lib/python3.12/unittest/mock.py", line 958, in assert_called_once_with
raise AssertionError(msg)
AssertionError: Expected 'mock' to be called once. Called 0 times.
----------------------------------------------------------------------
Ran 4 tests in 0.003s
FAILED (failures=1, errors=1)
Working on <MagicMock name='os.getcwd()' id='4449251648'>
Working on testing
[25]:
<unittest.main.TestProgram at 0x109289400>
raise an AttributeError:
AttributeError: Mock object has no attribute 'get_path'
Partial class mocking
A class can also be partially mocked by using mock.patch.object:
[26]:
from unittest import TestCase, mock, main
from worker import Worker, Helper
class TestWorkerModule(TestCase):
def test_partial_patching_decorator(self):
with mock.patch.object(Helper, 'get_path', return_value='testing'):
worker = Worker()
self.assertEqual(worker.helper.path, 'db')
self.assertEqual(worker.work(), 'testing')
@mock.patch.object(Helper, 'get_path', return_value='testing')
def test_partial_patching_decorator(self, mocked_helper_get_path):
worker = Worker()
self.assertEqual(worker.helper.path, 'db')
self.assertEqual(worker.work(), 'testing')
mocked_helper_get_path.assert_called_once()
main(argv=[''], verbosity=2, exit=False)
test_using_decorator (__main__.TestWorkMockingModule.test_using_decorator) ... ok
test_partial_patching_decorator (__main__.TestWorkerModule.test_partial_patching_decorator) ... ok
test_get_path (__main__.TestWorkerModuleRaisesError.test_get_path) ... ERROR
======================================================================
ERROR: test_get_path (__main__.TestWorkerModuleRaisesError.test_get_path)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/local/Cellar/python@3.12/3.12.5/Frameworks/Python.framework/Versions/3.12/lib/python3.12/unittest/mock.py", line 1390, in patched
with self.decoration_helper(patched,
File "/usr/local/Cellar/python@3.12/3.12.5/Frameworks/Python.framework/Versions/3.12/lib/python3.12/contextlib.py", line 137, in __enter__
return next(self.gen)
^^^^^^^^^^^^^^
File "/usr/local/Cellar/python@3.12/3.12.5/Frameworks/Python.framework/Versions/3.12/lib/python3.12/unittest/mock.py", line 1372, in decoration_helper
arg = exit_stack.enter_context(patching)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/Cellar/python@3.12/3.12.5/Frameworks/Python.framework/Versions/3.12/lib/python3.12/contextlib.py", line 526, in enter_context
result = _enter(cm)
^^^^^^^^^^
File "/usr/local/Cellar/python@3.12/3.12.5/Frameworks/Python.framework/Versions/3.12/lib/python3.12/unittest/mock.py", line 1539, in __enter__
raise TypeError(
TypeError: autospec creates the mock for you. Can't specify autospec and new.
----------------------------------------------------------------------
Ran 3 tests in 0.005s
FAILED (errors=1)
Working on <MagicMock name='os.getcwd()' id='4449406896'>
Working on testing
[26]:
<unittest.main.TestProgram at 0x1092894c0>
unittest.mock.patch
Patch an import module
unittest.mock is able to patch imports in the module under test using the patch function.
patch will intercept import statements identified by a string and return a Mock instance you can preconfigure using the techniques from unittest.Mock (see above).
Module under test (work.py):
import os
def work_on():
path = os.getcwd()
print(f'Working on {path}')
return path
The project module imports os and uses its getcwd() method , which we want to mock in our test.
Patch using a context manager (with statement)
When using the context manager patch, the patch ends when the with statement ends.
from unittest import TestCase, mock
from work import work_on
class TestWorkMockingModule(TestCase):
def test_using_context_manager(self):
with mock.patch('work.os') as mocked_os:
work_on()
mocked_os.getcwd.assert_called_once()
We specifically patch the work.os module, not os, as this would patch os for all modules, not just for work.py.
The test module imports the project module’s method
work_on()At the beginning of the test, the
work.osmodule (which is theosmodule in ourwork.pymodule) is patched with a MagickMock object (here calledmocked_os)When the
work_on()method is called afterward, thatMagicMockobject is called instead of the original module (os) - as no return value is definedwork_on()returns another MagicMock object - as we are not testing the correctness of the return value here, only checking if themocked_osexecuted thegetcwd()method, we do not care about the return value
The as statement in the decorator is optional. You may as well not mock the entire work.os module, but rather define a return value for the single function, that is called (getcwd()):
from unittest import TestCase, mock
from work import work_on
class TestWorkMockingModule(TestCase):
def test_using_return_value(self):
with mock.patch('work.os.getcwd', return_value='testing'):
assert work_on() == 'testing'
Patch using the decorator (@patch)
Using the @patch decorator allows to inject a mock into the test function. The patch is available for the entire function.
from unittest import TestCase, mock
from work import work_on
class TestWorkMockingModule(TestCase):
@mock.patch('work.os')
def test_using_decorator(self, mocked_os):
work_on()
mocked_os.getcwd.assert_called_once()
Here the work.os module is replaced with a MagicMock object.
Patching classes
To test project classes that interact with other project classes in isolation, the other project classes must be mocked (in order to determine test failure to a specific class and method, not by any of its dependency classes).
Example:
Project module (worker.py)
In this module, the Worker class needs to be tested for these two things:
the
WorkercallsHelperwithdbthe
Workerreturns the expected path supplied byHelper
import os
class Helper:
def __init__(self, path):
self.path = path
def get_path(self):
base_path = os.getcwd()
return os.path.join(base_path, self.path)
class Worker:
def __init__(self):
self.helper = Helper('db')
def work(self):
path = self.helper.get_path()
print(f'Working on {path}')
return path
Test module (test_worker.py)
Patch entire class
To test this, the Worker needs to be isolated from Helper, so that failures can be associated with the Worker class only.
Consequently, the entire Helper class must be patched:
from unittest import TestCase, mock
from worker import Worker
class TestWorkerModule(TestCase):
def test_patching_class(self):
with mock.patch('worker.Helper') as MockHelper:
MockHelper.return_value.get_path.return_value = 'testing'
worker = Worker()
MockHelper.assert_called_once_with('db')
self.assertEqual(worker.work(), 'testing')
Note the double return_value in the example, simply using MockHelper.get_path.return_value would not work since in the code we call get_path on an instance, not the class itself.
Alternatively, we can preconfigure the MockHelper instance and assign it as the return value of the worker.Helper call. Below, shown for both the context manager and the decorator way:
from unittest import TestCase, mock
from worker import Worker
class TestWorkerModule(TestCase):
mockHelperInstance = mock.MagicMock()
mockHelperInstance.get_path.return_value = 'testing'
# using patch context manager
def test_patch_class_context_manager(self):
with mock.patch('worker.Helper',
return_value=self.mockHelperInstance) as MockHelper:
worker = Worker()
MockHelper.assert_called_once_with('db')
self.assertEqual(worker.work(), 'testing')
# using patch class decorator
@mock.patch('worker.Helper', return_value=mockHelperInstance)
def test_patch_class_decorator(self, mock_helper):
worker = Worker()
mock_helper.assert_called_once_with('db')
self.assertEqual(worker.work(), 'testing')
Important
It is important to distinguish between mocking a class and mocking the instance of a class. Sometimes, it is necessary to mock the entire class, sometimes it might be sufficient to mock only an instance from that class.
Mocking the entire class allows for
* checking, in what way that class has been initialized
* instantiating multiple instances from it, which return a Mock object and
raises the call count
For the above worker.py module, both these tests pass:
from unittest import TestCase, mock
from worker import Worker
mockHelper = mock.MagicMock()
class TestWorkerModule(TestCase):
def setUp(self):
mockHelper.reset_mock()
self.mock_helper_instance = mockHelper.return_value
@mock.patch('worker.Helper', new=mockHelper)
def test_initialization(self):
Worker()
mockHelper.assert_called_once_with('db')
@mock.patch('worker.Helper', new=mockHelper)
def test_get_path(self):
self.mock_helper_instance.get_path.return_value = 'testing'
worker = Worker()
self.assertEqual(worker.work(), 'testing')
Speccing
The danger with mocks is that a Mock object returns a new MagicMock object to basically every attribute or method it is queried for, no matter if that attribute or method actually exists. If the mocked class changes signatures or an attribute, the Mockobject will still return the requested “thing” as another Mock, simply said
The Mock does not know about the object it is mocking.
To prevent this speccing can be added to a Mock, which makes it behave as the object being mocked. The easiest to use is autospec=True option.
Example:
Assuming the Helper class changed its get_path() method to get_folder(), but the call is not changed in the Worker class:
import os
class Helper:
def __init__(self, path):
self.path = path
def get_folder(self):
base_path = os.getcwd()
return os.path.join(base_path, self.path)
class Worker:
def __init__(self):
self.helper = Helper('db')
def work(self):
path = self.helper.get_path()
print(f'Working on {path}')
return path
When running the previous test without the speccing option, this would pass, as we mock the get_path method for the Mock instance although the original class does not contain this method anymore.
But with the autospec=True method, the Mockget_path() method, the Mock object checks for consistence with the original object. So
@mock.patch('worker.Helper', new=mockHelper, autospec=True)
def test_get_path(self):
self.mock_helper_instance.get_path.return_value = 'testing'
worker = Worker()
self.assertEqual(worker.work(), 'testing')
raise an AttributeError:
AttributeError: Mock object has no attribute 'get_path'
Partial class mocking
A class can also be partially mocked by using mock.patch.object:
from unittest import TestCase, mock
from worker import Worker, Helper
class TestWorkerModule(TestCase):
def test_partial_patching_decorator(self):
with mock.patch.object(Helper, 'get_path', return_value='testing'):
worker = Worker()
self.assertEqual(worker.helper.path, 'db')
self.assertEqual(worker.work(), 'testing')
@mock.patch.object(Helper, 'get_path', return_value='testing')
def test_partial_patching_decorator(self, mocked_helper_get_path):
worker = Worker()
self.assertEqual(worker.helper.path, 'db')
self.assertEqual(worker.work(), 'testing')
mocked_helper_get_path.assert_called_once()
Mocking built-in functions and environment variables
Previously, the print() call in Worker.work() was neglected, though it might be important to test, if that call was made.
Assuming this version of the work() method inside worker.py:
import os
def work_on_env():
path = os.path.join(os.getcwd(), os.environ['MY_VAR'])
print(f'Working on {path}')
return path
The path is concatenated by a MY_VAR environment variable and the os.getcwd() return value. The test:
from unittest import TestCase, mock
from worker import work_on_env
class TestBuiltin(TestCase):
def test_patch_dict_context_manager(self):
with mock.patch('worker.print') as mock_print:
with mock.patch('os.getcwd', return_value='/home/'):
with mock.patch.dict('os.environ', {'MY_VAR': 'testing'}):
self.assertEqual(work_on_env(), '/home/testing')
mock_print.assert_called_once_with('Working on /home/testing')
we patch the built-in
print()function for theworkermodule asmock_print(patch on import)we patch the
worker.work_on_env()method assigning “/home/” as the return valuewe patch the
os.environdictionary with a{'MY_VAR': 'testing'}dictionary
Nesting multiple context managers can be prevented by using multiple patch decorators:
from unittest import TestCase, mock
from worker import work_on_env
class TestBuiltin(TestCase):
@mock.patch('os.getcwd', return_value='/home/')
@mock.patch('worker.print')
@mock.patch.dict('os.environ', {'MY_VAR': 'testing'})
def test_patch_builtin_dict_decorators(self, mock_print, mock_getcwd):
self.assertEqual(work_on_env(), '/home/testing')
mock_print.assert_called_once_with('Working on /home/testing')
Note that the mock_getcwd must be passed into the test function, though it isn’t used.
— skipped ‘Mocking context managers’ here, might document later —
NEEDS TO BE CONTINUED…