在类方法中引发副作用并在调用方法中捕获的模拟异常给出“未引发”

时间:2019-11-13 17:48:27

标签: python-3.x unit-testing exception mocking pytest

我使用side_effect试图在调用模拟程序时引发异常,但遇到一个我不理解的DID NOT RAISE EXCEPTION错误。

在很大程度上基于此answer,我创建了一个简单的示例,其中有一个Query类和一个类方法make_request_and_get_response,该类方法可能引发多个异常。这些异常正在get_response_from_external_api的{​​{1}}方法中处理。

query.py

main.py

main.py

from urllib.request import urlopen
import contextlib
import urllib

class Query:
    def __init__(self, a, b):
        self.a = a
        self.b = b

        self.query = self.make_query()


    def make_query(self):
        # create query request using self.a and self.b
        return query


    def make_request_and_get_response(self):  # <--- the 'dangerous' method that can raise exceptions
        with contextlib.closing(urlopen(self.query)) as response:
            return response.read().decode('utf-8')

我正在使用from foo.query import * def get_response_from_external_api(query): try: response = query.make_request_and_get_response() except urllib.error.URLError as e: print('Got a URLError: ', e) except urllib.error.HTTPError as e: print('Got a HTTPError: ', e) # {{various other exceptions}} except Exception: print('Got a generic Exception!') # handle this exception if __name__ == "__main__": query = Query('input A', 'input B') result = get_response_from_external_api(query) return result 来模拟该“危险”方法(pytest),并带有针对特定异常的副作用。然后,我将继续创建一个模拟的make_request_and_get_response对象,以在调用Query时使用,期望此最后一次调用会产生'URLError'异常。

test_main.py

make_request_and_get_response

上面的测试给出以下错误:

import pytest
from unittest.mock import patch
from foo.query import Query
from foo.main import get_response_from_external_api


class TestExternalApiCall:
    @patch('foo.query.Query')
    def test_url_error(self, mockedQuery):
        with patch('foo.query.Query.make_request_and_get_response', side_effect=Exception('URLError')):
            with pytest.raises(Exception) as excinfo:
                q= mockedQuery()
                foo.main.get_response_from_external_api(q)
            assert excinfo.value = 'URLError'
            # assert excinfo.value.message == 'URLError' # this gives object has no attribute 'message'

1 个答案:

答案 0 :(得分:1)

Pytest无法检测到异常,因为您在get_response_from_external_api中正在捕获所有异常。根据您的要求,您可以选择以下选项:

  1. 不要在get_response_from_external_api中捕获异常。
  2. 捕获异常,执行所需的任何操作,然后重新引发它们。
  3. 使用capsys固定装置捕获正在打印的内容并对该输出进行断言,而不是检测pytest.raises的异常。