在类方法中引发副作用并在调用方法中捕获的模拟异常给出“未引发" [英] Mock exception with side effect raised in class method and caught in calling method gives 'did not raise'
问题描述
使用 side_effect ,我是尝试在调用模拟程序时引发异常,但出现一个我不理解的DID NOT RAISE EXCEPTION
错误.
Using side_effect, I am trying to raise an exception when a mock is called but I get a DID NOT RAISE EXCEPTION
error that I do not understand.
主要基于此答案,我创建了一个简单的示例,其中有一个Query
类和一个类方法make_request_and_get_response
会引发多个异常.这些异常是在main.py
中的get_response_from_external_api
方法中处理的.
Based largely on this answer, I have created a simple example where there is a Query
class with a class method make_request_and_get_response
which can raise several exceptions. These exceptions are being handled within the get_response_from_external_api
method in main.py
.
query.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')
main.py
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
对象,该对象将在调用make_request_and_get_response
时使用,并期望最后一次调用会给出"URLError"异常.
Using pytest
, I am trying to mock that 'dangerous' method (make_request_and_get_response
) with a side effect for a specific exception. Then, I proceed with creating a mocked Query
object to use when calling the make_request_and_get_response
with the expectation that this last call give a 'URLError' exception.
test_main.py
test_main.py
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'
上面的测试给出以下错误:
The test above gives the following error:
> foo.main.get_response_from_external_api(q)
E Failed: DID NOT RAISE <class 'Exception'> id='72517784'>") == 'URLError'
推荐答案
Pytest无法检测到异常,因为在get_response_from_external_api
中您正在捕获所有异常.根据您的要求,您可以选择以下选项:
Pytest cannot detect an exception because in get_response_from_external_api
you are catching all of them. Depending on your requirements, you have these options:
- 不要在
get_response_from_external_api
中捕获异常. - 捕获异常,执行所需的任何操作,然后重新引发它们.
- 使用
pytest.raises异常"rel =" nofollow noreferrer> capsys 固定装置以捕获正在打印的内容并在该输出上进行断言.
- Don't catch the exceptions in
get_response_from_external_api
. - Catch the exceptions, do whatever you want and then re-raise them.
- Instead of detecting an exception with
pytest.raises
, use capsys fixture to capture what is being printed and make assertions on that output.
这篇关于在类方法中引发副作用并在调用方法中捕获的模拟异常给出“未引发"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!