在类方法中引发副作用并在调用方法中捕获的模拟异常给出“未引发" [英] Mock exception with side effect raised in class method and caught in calling method gives 'did not raise'

查看:106
本文介绍了在类方法中引发副作用并在调用方法中捕获的模拟异常给出“未引发"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 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:

  1. 不要在get_response_from_external_api中捕获异常.
  2. 捕获异常,执行所需的任何操作,然后重新引发它们.
  3. 使用pytest.raises异常"rel =" nofollow noreferrer> capsys 固定装置以捕获正在打印的内容并在该输出上进行断言.
  1. Don't catch the exceptions in get_response_from_external_api.
  2. Catch the exceptions, do whatever you want and then re-raise them.
  3. Instead of detecting an exception with pytest.raises, use capsys fixture to capture what is being printed and make assertions on that output.

这篇关于在类方法中引发副作用并在调用方法中捕获的模拟异常给出“未引发"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆