简体   繁体   中英

Use PyTest to test the decorated exception handler is called

I use the decorator to handle the exception in Python. Here is the decorator function:

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

Now I would like to use Pytest when the SubProcessException raised this function is called. Something like:

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

But the mock did not get the call, failed with message AssertionError: Expected 'docker_exception_handler' to have been called once. Called 0 times AssertionError: Expected 'docker_exception_handler' to have been called once. Called 0 times I do not know why.

Decorators applied in import time, so there is not much sense to mock them and asserting something in runtime.

In your case you could mock the logger and check if it was called with right arguments. Here I'm using mocker fixture from pytest-mock

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__])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM