I have a problem in writing integration test for some function that calls other function which is decorated. Suppose the following definitions:
# myproj.py
import logging
def catch_every_error(func):
logger = logging.getLogger("mylogger")
def wrapper(*args, **kwargs):
try:
result = func(*args, **kwargs)
except Exception as e:
logger.exception("")
else:
return result
return wrapper
@catch_every_error
def problematic_func():
pass
def func_under_test():
# doing something very critical here
# ....
problematic_func()
I need to write test to ensure that any exception raised inside problematic_func
will not be propagated to func_under_test
. For this reason, I used mocking like below:
import unittest
from unittest.mock import patch
from myproj import func_under_test
class MyTestCase(unittest.TestCase):
@patch("myproj.problematic_func")
def test_no_exception_raises(self, mock_problematic_func):
mock_problematic_func.side_effect = Exception("Boom")
try:
func_under_test()
except Exception:
self.fail(
"exception in problematic function propagated to 'func_under_test'"
)
if __name__ == "__main__":
unittest.main()
Problem is that I can’t pass this test. Patching problematic_func
caused removal of decorator applied to that function and exceptions are not catched. For applying decorator manually, I tried:
mock_problematic_func = catch_every_error(mock_problematic_func)
This also doesn’t result with successful test passing. Exception is still raised when calling func_under_test
in my test case. How should I test that any exception raised inside problematic_func
doesn’t cause failure in func_under_test
?
Note: Please don’t suggest writing test for catch_every_error
decorator. I am trying to fulfill integration test for func_under_test
.
Advertisement
Answer
Working version of the test above is like below:
import unittest
from unittest.mock import patch
import myproj
class MyTestCase(unittest.TestCase):
@patch("myproj.problematic_func")
def test_no_exception_raises(self, mock_problematic_func):
mock_problematic_func.side_effect = Exception("Boom")
myproj.problematic_func = myproj.catch_every_error(mock_problematic_func)
try:
myproj.func_under_test()
except Exception:
self.fail(
"exception in problematic function propagated to 'func_under_test'"
)
if __name__ == "__main__":
unittest.main()
Previously, I tried (with no successful result):
from myproj import catch_every_error
mock_problematic_func = catch_every_error(mock_problematic_func)
For some reason (I don’t know exactly), importing function with from
statement and decorating manually didn’t work. Although importing whole module (import myproj
) and manually decorating with resetting attribute (myproj.problematic_func =
) worked.