Let's say we have a function dosomething
whose argument is an instance of class A. That class A has an attribute which is an instance of class B, and B has an attribute containing a list of objects of class C. So the function looks something like this:
def dosomething(objA):
alist = objA.objB.some_attribute
for objC in alist:
print objC.name
print objC.value
To test this function, we would have to mock class A. Without MagicMock, we would need to create a mock for multiple classes, like so:
class C:
def __init__(self, name=None, value=None):
self.name = name
self.value = value
class B:
def __init__(self):
self.some_attribute = [] # this will be a list of instances of class C
class A:
def __init__(self):
self.objB = B()
Then to use this in your unit test:
import unittest
class RandomTests(unittest.TestCase):
def test_dosomething(self):
a = A()
a.objB.some_attribute = [C('somename', 'somevalue')]
dosomething(a)
# then assert one output
All these just to pass the correction argument into the function dosomething
so that it doesn't complain about attribute errors.
But with magic mock, we don't need to manually mock all our classes, and it just becomes:
import unittest
from mock import MagicMock
class RandomTests(unittest.TestCase):
def test_dosomething(self):
a = MagicMock()
a.objB.some_attribute = [MagicMock(name='somename', value='somevalue')]
dosomething(a)
# then assert on output
It's just like magic!