Ошибка теста повышения Pytest для request.raise_for_status()

Недавно я начал использовать pytest, а совсем недавно начал использовать mock для имитации запросов библиотека. Я сделал объект request.Response в порядке, и для кода состояния 200 он работает нормально. Что я пытаюсь сделать здесь, так это использовать raise_for_status() для проверки ошибки превышения лимита скорости и проверки обработки исключения с помощью pytest.

Я использую параметр Mock side_effect, который, кажется, запускает исключение, на которое я надеюсь, но pytest, похоже, не распознает, что это произошло, и не проходит тест.

Какие-нибудь мысли? Я уверен, что это что-то очевидное, что мне не хватает!

Код, который у меня есть для класса:

class APIClient:
    def get_records(self, url):
        try:
            r = requests.get(url)
            r.raise_for_status()
            return r.json()
        except requests.HTTPError as e:
            print("Handling the exception")

В тестовом классе у меня есть:

@pytest.fixture
def http_error_response(rate_limit_json):
    mock_response = mock.Mock()
    mock_response.json.return_value = rate_limit_json
    mock_response.status_code = 429

    mock_response.raise_for_status.side_effect = requests.exceptions.HTTPError

    return mock_response


class TestRecovery(object):

    @mock.patch('requests.get')
    def test_throws_exception_for_rate_limit_error\
    (self, mock_get, api_query_object, http_error_response):

        mock_get.return_value = http_error_response
        print(http_error_response.raise_for_status.side_effect)

        url = api_query_object.get_next_url()

        with pytest.raises(requests.exceptions.HTTPError):
            api_query_object.get_records(url)

Вывод, который я получаю:

    with pytest.raises(requests.exceptions.HTTPError):
>           api_query_object.get_records(url)
E           Failed: DID NOT RAISE

---------------------- Captured stdout call ---------------------- 
<class 'requests.exceptions.HTTPError'>
Handling the exception

person huwf    schedule 20.02.2016    source источник
comment
Ваш тест предполагает, что метод вызовет ошибку, но он явно фиксирует ошибку и вместо этого печатает сообщение. Либо тест неверный, либо код. Вместо этого вы можете проверить, действительно ли вызывается raise_for_status, а затем в результате вызывается print. В качестве альтернативы (и предпочтительно, на мой взгляд), пусть метод действительно вызовет ошибку, а затем обработает ее в вызывающем объекте.   -  person jonrsharpe    schedule 20.02.2016
comment
Неожиданный результат теста см. в комментарии @jonrsharpe. В качестве общего примечания: в то время как unittest.mock отлично подходит для общего насмешливого, фальшивого а заглушка, в частности для requests, requests-mock может быть более интуитивно понятной.   -  person das-g    schedule 20.02.2016
comment
@jonrsharpe Спасибо! В этом была проблема, я думаю, я пытался сделать две вещи одновременно - проверить, произошло ли исключение и было ли оно обработано. Я также думаю, что мне, вероятно, следует изменить поток и обработчик в вызывающем абоненте, хотя мне придется проверить, как, например. повторная попытка из-за ошибок сервера. Для тестирования обработки исключений в целом, я думаю, мне следует поместить функцию обработки в блок except и проверить, что вызывается?   -  person huwf    schedule 20.02.2016
comment
@das-g Хорошая ссылка! Выглядит намного проще :)   -  person huwf    schedule 20.02.2016
comment
Нет, если вам не нужна функция обработки ошибок; опять же, я бы просто позволил ошибке появиться и обработать ее снаружи, где вы можете решить, хотите ли вы позвонить снова, проигнорировать ее или позволить ей всплыть дальше по цепочке вызовов.   -  person jonrsharpe    schedule 20.02.2016
comment
@huwf Stack Exchange всегда настоятельно рекомендовал пользователям отвечать на свои вопросы. Вы можете сделать это сейчас, когда ваша проблема решена   -  person xverges    schedule 21.09.2018


Ответы (1)


Вы указываете pytest ожидать исключения, которое должно быть вызвано в APIClient.get_records, но внутри этого определения метода вы уже захватываете исключение и просто выполняете печать.

Исключение на самом деле происходит, и это доказано, увидев результат вашей печати в выводе консоли.

Вместо этого вы должны либо проверить с макетом, что был вызван метод raise_for_status.

person lucrib    schedule 26.08.2020