13

我有以下测试代码检查函数中引发的异常。我希望测试能够通过,但会显示失败。这是测试代码:

import unittest

# define a user-defined exception
class MyException(Exception):
    def __str__(self):
        return repr("ERROR: Just raised my exception!")

# this is my main class with a method raising this exception
class MyMainObject(object):

    def func(self):
        raise MyException()

# the test class
class TestConfig(unittest.TestCase):

    def test_1(self):

        other = MyMainObject()
        self.assertRaises(MyException, other.func())

# calling the test
if __name__ == '__main__':    
    unittest.main()

other.func()assert 语句中调用时,MyException会引发(可以轻松检查)。所以,assertRaises测试应该通过测试,因为other.func()失败MyException,但是:

....
MyException: 'ERROR: Just raised my exception!'

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (errors=1)

我看不出有什么问题,所以我希望能就这个问题提供一些意见。

4

2 回答 2

29

assertRaises为您调用该函数。通过自己调用它,在可以测试它之前 引发异常。assertRaises

将您的代码更改为:

self.assertRaises(MyException, other.func)

它会正常工作。或者,您可以assertRaises用作上下文管理器(python 2.7 及更高版本):

with self.assertRaises(MyException):
    other.func()

用作上下文管理器assertRaises有一个额外的优势,您现在可以检索异常实例并对其执行进一步的测试:

with self.assertRaises(MyException) as raises_cm:
    other.func()

exception = raises_cm.exception
self.assertEqual(exception.args, ('foo', 'bar'))
于 2012-09-20T16:31:40.983 回答
7

由于语言的规则,在输入被调用函数的代码之前对参数进行评估(这通常是一件好事)。因此,assertRaises无法捕获在评估参数期间发生的异常。解决方法(在多个 API 中)是您将一个可调用对象传递给诸如 之类的方法assertRaises,这样他们就可以在他们可以控制的地方对其进行评估并且可以捕获异常。如果整个参数是一个方法调用,绑定方法的魔力可以让您非常优雅地陈述这一点,而不会lambda或这样愚蠢:

self.assertRaises(MyException, other.func) # <- note, no parentheses after func
于 2012-09-20T16:31:38.690 回答