Примечание. Этот вопрос основан на предыдущем вопросе, который я задавал, но изменен в соответствии с этот ответ.
Используя side_effect, я пытаюсь поднять исключение 'URLError'
при вызове макета, но я получаю ошибку DID NOT RAISE
, которую не понимаю.
У меня есть класс Query
с методом класса make_request_and_get_response
, который может вызвать несколько исключений. Я не перехватываю исключение 'URLError'
в методе get_response_from_external_api
в main.py
, поэтому я должен ожидать возбуждения и, впоследствии, имитирования его исключения.
запрос.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.HTTPError as e:
print('Got a HTTPError: ', e)
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».
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'
Приведенный выше тест выдает следующую ошибку:
> foo.main.get_response_from_external_api(q)
E Failed: DID NOT RAISE <class 'Exception'> id='72517784'>") == 'URLError'
Та же ошибка возникает, даже если я поймаю исключение 'URLError'
, а затем повторно вызову его в get_response_from_external_api
.
Может ли кто-нибудь помочь мне понять, чего мне не хватает, чтобы иметь возможность вызвать исключение в pytest?
Обновить в соответствии с ответом @SimeonVisser:
Если я изменю main.py
, чтобы удалить случай except Excpetion
:
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)
затем тест в test_main.py
:
def test_url_error2(self):
mock_query = Mock()
mock_query.make_request_and_get_response.side_effect = Exception('URLError')
with pytest.raises(Exception) as excinfo:
get_response_from_external_api(mock_query)
assert str(excinfo.value) == 'URLError'
Тест проходит нормально.