如何在Python 3中模拟连接和超时错误?

时间:2019-07-10 10:09:33

标签: python-3.x mocking pytest

我是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 个答案:

答案 0 :(得分:1)

如果要模拟异常,请在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)

答案 1 :(得分:1)

长话短说:您没有收到消息,因为您未指定消息。

您可能要检查'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异常所定义的行为。