-
Notifications
You must be signed in to change notification settings - Fork 12
The `patches` test fixture
The patches
fixture provides a way of patching multiple objects
in a python module.
Essentially it provides a context manager that provides nested context managers
of objects patched with unittest.mock.patch
.
Using the patch
module from unittest.mock
you can ordinarily do the following:
from unittest.mock import patch
from path.to.my.module import MyClass
def test_something1():
with patch("path.to.my.module.MyClass.my_method1") as m_method1:
MyClass().other_method_that_calls_my_method1()
If you wanted to patch multiple objects, properties, methods etc. you would then need to nest the context managers as follows:
from unittest.mock import patch
from path.to.my.module import MyClass
def test_something2():
with patch("path.to.my.module.MyClass.my_method1") as m_method1:
with patch("path.to.my.module.MyClass.my_method2") as m_method2:
MyClass().other_method_that_calls_my_methods()
If you have a lot of objects to patch, the above method can get pretty complex with deeply nested context managers and a lot of repetition of the module path.
The patches
fixture provides a way to do the above more simply and concisely.
Using patches
the test_something2
test could be rewritten as follows:
from unittest.mock import patch
from path.to.my.module import MyClass
def test_something3(patches):
patched = patches(
"MyClass.method1",
"MyClass.method2",
prefix="path.to.my.module")
with patched as (m_method1, m_method2):
MyClass().other_method_that_calls_my_methods()
Sometimes you need to patch an object with kwargs
, for example if you are
patching an object's @property
you may wish to call unittest.mock.patch
with new_callable=PropertyMock
.
The args
you call the patches
function with represent the objects to be patched.
If an arg
is a string the object will be patched without any kwargs.
If, on the other hand, the arg
is a tuple containing two items, a string and a
dict, the first item represents the object to be mocked, and the second the kwargs
to patch the object with.
For example, to test a class property named property1
you might:
from unittest.mock import patch, PropertyMock
from path.to.my.module import MyClass
def test_something4(patches):
patched = patches(
("MyClass.property1", <-- mocked property
dict(new_callable=PropertyMock)),
"MyClass.method1", <-- mocked method
prefix="path.to.my.module")
with patched as (m_property1, m_method1):
MyClass().method_that_calls_property1_and_method1()