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.