当前位置: 首页 > 知识库问答 >
问题:

无法捕获模拟异常,因为它没有继承BaseException

汪坚
2023-03-14

我正在做的一个项目涉及到连接到远程服务器,等待响应,然后根据响应执行操作。我们捕获了几个不同的异常,并且根据捕获的异常的不同而有不同的行为。例如:

def myMethod(address, timeout=20):
    try:
        response = requests.head(address, timeout=timeout)
    except requests.exceptions.Timeout:
        # do something special
    except requests.exceptions.ConnectionError:
        # do something special
    except requests.exceptions.HTTPError:
        # do something special
    else:
        if response.status_code != requests.codes.ok:
            # do something special
        return successfulConnection.SUCCESS

为了测试这一点,我们编写了一个如下所示的测试

class TestMyMethod(unittest.TestCase):

    def test_good_connection(self):
        config = {
            'head.return_value': type('MockResponse', (), {'status_code': requests.codes.ok}),
            'codes.ok': requests.codes.ok
        }
        with mock.patch('path.to.my.package.requests', **config):
            self.assertEqual(
                mypackage.myMethod('some_address',
                mypackage.successfulConnection.SUCCESS
            )

    def test_bad_connection(self):
        config = {
            'head.side_effect': requests.exceptions.ConnectionError,
            'requests.exceptions.ConnectionError': requests.exceptions.ConnectionError
        }
        with mock.patch('path.to.my.package.requests', **config):
            self.assertEqual(
                mypackage.myMethod('some_address',
                mypackage.successfulConnection.FAILURE
            )
ERROR: test_bad_connection (test.test_file.TestMyMethod)
----------------------------------------------------------------
Traceback (most recent call last):
  File "path/to/sourcefile", line ###, in myMethod
    respone = requests.head(address, timeout=timeout)
  File "path/to/unittest/mock", line 846, in __call__
    return _mock_self.mock_call(*args, **kwargs)
  File "path/to/unittest/mock", line 901, in _mock_call
    raise effect
my.package.requests.exceptions.ConnectionError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "Path/to/my/test", line ##, in test_bad_connection
    mypackage.myMethod('some_address',
  File "Path/to/package", line ##, in myMethod
    except requests.exceptions.ConnectionError:
TypeError: catching classes that do not inherit from BaseException is not allowed

共有1个答案

臧亦
2023-03-14

我可以用一个最小的例子重现这个错误:

py:

class MyError(Exception):
    pass

class A:
    def inner(self):
        err = MyError("FOO")
        print(type(err))
        raise err
    def outer(self):
        try:
            self.inner()
        except MyError as err:
            print ("catched ", err)
        return "OK"

没有嘲讽的测试:

class FooTest(unittest.TestCase):
    def test_inner(self):
        a = foo.A()
        self.assertRaises(foo.MyError, a.inner)
    def test_outer(self):
        a = foo.A()
        self.assertEquals("OK", a.outer())
class FooTest(unittest.TestCase):
    def test_inner(self):
        a = foo.A()
        self.assertRaises(foo.MyError, a.inner)
    def test_outer(self):
        with unittest.mock.patch('foo.MyError'):
            a = exc2.A()
            self.assertEquals("OK", a.outer())
ERROR: test_outer (__main__.FooTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "...\foo.py", line 11, in outer
    self.inner()
  File "...\foo.py", line 8, in inner
    raise err
TypeError: exceptions must derive from BaseException

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<pyshell#78>", line 8, in test_outer
  File "...\foo.py", line 12, in outer
    except MyError as err:
TypeError: catching classes that do not inherit from BaseException is not allowed

这里我得到了第一个TypeError,这是您没有的,因为当您使用'requests.exceptions.connectionError':requests.exceptions.connectionError强制执行true异常时,我引发了一个mock。但是问题仍然是except子句试图捕获模拟。

TL/DR:当您模拟完整的requests包时,except requests.exceptions.ConnectionError子句试图捕获模拟。由于模拟不是真正的baseException,它会导致错误。

我所能想象的唯一解决方案是不模拟完整的请求,而只模拟不是异常的部分。我必须承认,除了这个以外,我找不到如何说mock mock所有东西,但是在您的示例中,您只需要修补requests.head。所以我认为这应该奏效:

def test_bad_connection(self):
    with mock.patch('path.to.my.package.requests.head',
                    side_effect=requests.exceptions.ConnectionError):
        self.assertEqual(
            mypackage.myMethod('some_address',
            mypackage.successfulConnection.FAILURE
        )

也就是说:只修补head方法,并将异常作为副作用。

 类似资料:
  • 问题内容: 我正在一个项目中,该项目涉及连接到远程服务器,等待响应,然后根据该响应执行操作。我们捕获了两个不同的异常,并且根据捕获的异常而表现不同。例如: 为了测试这一点,我们编写了如下测试 如果我直接运行该函数,一切都会按预期进行。我什至通过在函数的子句中进行测试。但是当我运行单元测试时,我得到 我试图更改要修补的异常,但得到的错误大致相同。 我已经读过,所以我认为它在某处一定是一个不好的选择,

  • 所以 我有一个函数,有一个回调,所以我把它包装在一个挂起函数使用,但当它错误了,它是崩溃整个应用程序。 这里有一个概念是正在发生的事情。 2022-03-04 16:09:45.410 19289-19438/in.app.androidE/AndreidRuntime: FATAL EXCEPTION: DefaultDispatcher-Worers-3进程:in.app.android,PI

  • 我正在尝试使用以下代码使用流 API 获取 S3 对象的文件大小: 如果该项不存在,我会得到以下错误: [2015年10月13日星期二23:03:32][错误][客户端54.225.205.152]PHP警告:找不到文件或目录:s3://mybucket/myfile.jpg在/var/www/vendor/Aws/Aws-SDK-PHP/src/Aws/S3/stream wrapper . P

  • 我这里有我的问题的简化版本。A类有一个受保护的方法。类B继承了这个方法。 我现在用Mockito编写一个单元测试,它在另一个包测试中,我想测试方法。为此,我需要模拟getString()调用。由于该方法受到保护,并且我的测试类位于不同的包中,所以我不能使用。问题是,我监视类B。所以我不能使用。 我尝试通过反射获得受保护的方法: 但是我不知道如何在中使用这个。

  • 我通过激发Baeldung在Spring Security页面上的防止暴力身份验证尝试,为我的登录服务实现了暴力阻止机制,如下所示: 当用户未经验证时,LoginService抛出InvalidCredentialException(),然后我试图在AuthenticationFailureListener类中捕获此异常: 当出现错误时,则登录测试服务。将调用loginFailed()方法。然而,

  • 问题内容: 嗨,我刚刚开始将Spring和Hibernate4和maven一起使用。基本上,我的类层次结构是HUmanMicroTask从MicroTask扩展而来。将来可能会从MicroTask扩展其他几个类。我试图为每个具体的类创建一个表,这是使用spring3和hibernate 4来启动和运行的最简单方法。但是,当我运行代码时。我不断收到以下异常 尽管我看过很多论坛,但我不确定要在哪里犯错