装饰功能的集成测试

Integration test for decorated function

我在为某些调用其他修饰函数的函数编写集成测试时遇到问题。假设有以下定义:

# 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()

我需要编写测试以确保 problematic_func 内引发的任何异常都不会传播到 func_under_test。出于这个原因,我使用了如下模拟:

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()

问题是我不能通过这个测试。修补 problematic_func 导致删除应用于该函数的装饰器,并且未捕获异常。对于手动应用装饰器,我尝试了:

    mock_problematic_func = catch_every_error(mock_problematic_func)

这也不是成功通过测试的结果。在我的测试用例中调用 func_under_test 时仍然会出现异常。我应该如何测试 problematic_func 中引发的任何异常不会导致 func_under_test 中的失败?

注意:请不要建议为catch_every_error装饰器编写测试。我正在尝试完成 func_under_test.

的集成测试

上面测试的工作版本如下:

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()

之前,我尝试过(没有成功的结果):

from myproj import catch_every_error

mock_problematic_func = catch_every_error(mock_problematic_func)

由于某些原因(我不太清楚),使用 from 语句导入函数并手动装饰不起作用。虽然导入整个模块 (import myproj) 并使用重置属性手动装饰 (myproj.problematic_func =) 有效。