Here the ABC()
and obj.print_1()
get called during the import time and it prints "making object" and "printed 1" respectively. How can we mock all the three functions, __init__()
, print_1()
, and print_2()
?
xyz.py
from abc import ABC
obj = ABC()
obj.print_1()
def func():
return obj.print_2(2)
abc.py
class ABC():
def __init__(self):
print("making object")
def print_1():
print("printed 1")
return None
def print_2(val):
print("printed ", val)
return None
CodePudding user response:
Indeed, as soon as you import xyz
, it will import abc
and create an instance then call a method on it.
Solution : import abc
yourself BEFORE xyz
EVER GETS IMPORTED, and mock the methods defined in the class. And because we can't import a method, patch.object
is required.
Note : I added a self
as parameter in your ABC.print_1
method, otherwise it would be incorrect. Otherwise make it @staticmethod
Here is the test file I used :
import unittest
import unittest.mock as mock
from so74709409_abc import ABC
# no import of `xyz` here !
class Tests(unittest.TestCase):
def test__xyz_obj_calls_print1(self):
# __init__ must return None
with mock.patch.object(ABC, "__init__", **{"return_value": None}) as mock_init, \
mock.patch.object(ABC, "print_1") as mock_print1, \
mock.patch.object(ABC, "print_2") as mock_print2:
from so74709409_xyz import func # import now !
func()
mock_init.assert_called_once()
mock_print1.assert_called_once_with()
mock_print2.assert_called_once_with(2)
if __name__ == "__main__":
unittest.main()
But this is not very robust, if the module was already imported (maybe indirectly) before the test run, the import
inside the test won't have any effect, and so it will fail (mocks not getting called). It can be a pain in a real test suite (with many tests running in sequence) because the previous test will already have imported xyz
.
That's why it's better to do these kind of things in a if __name__=="__main__"
, or in a function called deliberately.
(beware : I assume you choose abc
as a dummy name, but it is actually a standard library module for Abstract Base Classes)