What is the difference between using mock.Mock()
vs mock.patch()
?
When to use mock.Mock()
and when to use mock.patch()
I've read that Mock is used to replace something that is used in the current scope, vs, patch is used to replace something that is imported and/or created in another scope. Can someone explain what that means?
I'm not completely sure if I understood your question, but I'll give it a try.
As described in the documentation, Mock
objects (actually MagickMock
instances) are created by using the patch
decorator:
from unittest.mock import patch
@patch('some_module.some_object')
def test_something(mocked_object):
print(mocked_object)
This gives something like:
<MagicMock name='some_object' id='1870192381512'>
This is eqivalent to:
def test_something():
with patch('some_module.some_object') as mocked_object:
print(mocked_object)
This gives you the possibility to replace any object by a mock object to avoid calling the actual production code and/or to check how the original object is called (if the object is a function). The reason why using patch
(or some similar methods) is preferred is that this ensures that the patch is reverted after the test (or after the context manager scope in the second case), so there are no side effects on other tests or other code.
To cite the documentation:
The patch decorators are used for patching objects only within the scope of the function they decorate. They automatically handle the unpatching for you, even if exceptions are raised. All of these functions can also be used in with statements or as class decorators.
You are also able to create a Mock
object manually and assign it to an object - I assume this is what you mean in your question. If you do this instead of using patch
, you are responsible to reset the previous state yourself. As this is more error-prone, I would advice to the dedicated methods for patching if possible.
Where this does not matter is in local objects and other mocks. Mocking local objects is seldom needed, but Mock
instances are often created in conjunction with patching an object to preserve the instance of a mock object for later check:
@mock.patch('my_functions.MyClass')
def test_object(mock_class):
arg1 = Mock()
arg2 = Mock()
do_something(arg1, arg2)
# check that do_something creates MyClass with the given arguments
mock_class.assert_called_with(arg1, arg2)
In this case the case will only be used as an argument to a mock object, so no reset is needed.
To summarize:
patch
is a convenience decorator/context manager function to replace objects with mock objects (or other objects) and reset the previous state after finishing or in case of an exceptionMock
or derived objects are created by mock.patch
, and can also be created manually. Manually created mocks are usually only used to patch local functions or other mocks where no reset is needed.