使用 PyTest 测试被调用的装饰异常处理器

Use PyTest to test the decorated exception handler is called

我使用装饰器来处理Python中的异常。这是装饰函数:

def docker_exception_handler(func):
    def wrapper(*args, **kwargs):
        logger = logging.getLogger('docker_exception')
        try:
           func(*args, **kwargs)
        except SubProcessException:
           logger.critical(
               f'Failed to pull {args[1]} in function {func.__name__}\n')

    return wrapper

现在我想在调用此函数时引发 SubProcessException 时使用 Pytest。 类似于:

@docker_exception_handler
def trigger_docker_error(class_name, docker_image):
    raise PullDockerImageError

def test_docker_error():
    with patch.object(customized_exceptions,
                  'docker_exception_handler') as mock:
         trigger_docker_error("test", "test_docker_image")
    mock.assert_called_once()

但是模拟没有接到电话,失败并显示消息 AssertionError: Expected 'docker_exception_handler' to have been called once. Called 0 times 不知道为什么。

装饰器在导入时应用,因此模拟它们并在运行时声明某些东西没有多大意义。

在您的情况下,您可以模拟记录器并检查是否使用正确的参数调用它。我在这里使用 mocker 来自 pytest-mock

的 fixture
import functools
import logging

def exception_handler(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        logger = logging.getLogger('docker_exception')
        try:
           func(*args, **kwargs)
        except Exception:
           logger.critical(
               f'Failed to pull {args[1]} in function {func.__name__}\n')
    return wrapper

@exception_handler
def trigger_error(class_name, docker_image):
    raise TypeError()

def test_error(mocker):
    logger = logging.getLogger('docker_exception')
    mock = mocker.patch.object(logger, 'critical')

    trigger_error("test", "test_docker_image")

    mock.assert_called_once()
    mock.assert_called_with(f'Failed to pull test_docker_image in function trigger_error\n')

if __name__ == "__main__":
    import pytest
    pytest.main([__file__])