Как я могу издеваться над ошибкой подключения и тайм-аута в Python 3? - PullRequest
1 голос
/ 10 июля 2019

Я новичок в Python.Я пытаюсь смоделировать исключение в моем модульном тесте и проверить мой блок кода;однако сообщение об исключении всегда пусто.Это ниже рекомендуемый способ макетировать исключение?Также, как я могу убедиться, что сообщение об исключении не пустое?

import pytest
import requests
from unittest.mock import patch

#Unit Test
@patch('requests.get')
def test_exception(mock_run):
    mock_run.side_effect = requests.exceptions.ConnectionError()
    with pytest.raises(SystemExit) as sys_exit:
       method_to_test()
    assert 'Error ' in str(sys_exit.value) # Here sys_exit.value is always empty

#Method to Test
def method_to_test():
    try:
        response = requests.get('some_url', verify=False, stream=True)
        response.raise_for_status()
    except (requests.exceptions.HTTPError,
            requests.exceptions.ConnectionError,
            requests.exceptions.Timeout) as err:
        msg = f'Failure: {err}' # Here err is always empty
        raise SystemExit(msg)

Ответы [ 2 ]

1 голос
/ 10 июля 2019

Короче говоря: Вы не получите сообщение, потому что не указали его.

Возможно, вы захотите проверить 'Failure: ' вместо 'Error: ', посколькуэто то, что вы префикс исходного сообщения исключения.Это может быть реальной проблемой в вашем коде, а не пустым строковым представлением исключения, которое вы вызываете в своем тесте.

Почему str(err) пусто?

Посмотрите на иерархию классов:

  • BaseException
  • Exception
  • IOError
  • requests.RequestException
  • requests.ConnectionError

IOError переопределяет __str__, если конструктору передано более одного аргумента, но в противном случае применяется поведение BaseException:

Если str ()вызывается для экземпляра этого класса, возвращается представление аргумента (ов) к экземпляру или пустая строка, когда не было аргументов.https://docs.python.org/3/library/exceptions.html#BaseException

>>> import requests
>>> str(requests.exceptions.ConnectionError())
''
>>> str(requests.exceptions.ConnectionError('foo'))
'foo'
>>> str(requests.exceptions.ConnectionError('foo', 'bar'))
'[Errno foo] bar'

Последний пример - это поведение, определяемое исключением IOError.

1 голос
/ 10 июля 2019

Если вы хотите смоделировать исключение, raise исключение в вашем блоке try, точно так же, как вы вызываете исключение в своем блоке except.Когда вы сделаете это, вы можете передать строковый аргумент в качестве сообщения об исключении -

raise requests.exceptions.HTTPError("Test this error")

, который отфильтрует сообщение в блок except.

С вашим примером:

def method_to_test():
        try:
            # ADD EXCEPTION HERE
            raise requests.exceptions.HTTPError('Throwing an exception here!')
            response = requests.get('some_url', verify=False, stream=True)
            response.raise_for_status()
        except (requests.exceptions.HTTPError,
                requests.exceptions.ConnectionError,
                requests.exceptions.Timeout) as err:
            # err will now be 'Throwing an exception here!'
            msg = f'Failure: {err}' # Here err is always empty
            raise SystemExit(msg)
...