在 Python 中进行单元测试时在 类 中传递异常

Passing exceptions across classes while unit-testing in Python

假设有两个 Python classes,其中第一个 (Class 1) 包含一个函数 ( function_c1) 包含一些语句 (some_statement),如果为真 - return 是自定义异常 (MyException)。进一步假设第二个 class (Class 2) 执行第一个 class 并希望传递自定义异常(即 return 相同的异常本身)。下面的代码举例说明了这种情况:

class Class1:
    ''' My nifty class 1. '''
    def __init__(self):
        pass
    def function_c1(self, some_input):
        ''' A function of class 1. '''
        if some_statement(some_input):
            return MyException('Some error message.')
        return True

class Class2:
    ''' My nifty class 2. '''
    def __init__(self):
        pass
    def function_c2(self, some_input):
        ''' A function of class 2. '''
        my_handle = Class1()
        try:
            my_handle.function_c1(some_input)
        except MyException as e:
            return MyException(e)
        return True

为什么 Class 2 return 'True' 不管 Class 1 return 是否异常?


编辑 1:在上面的示例中,我故意选择 return 而不是 raise 异常以呈现 class 1 适用于单元测试。

self.assertRaises(Class1().function_c1(some_input))

鉴于我对 Python 的不完全理解,我看到只有两个选择可以吃蛋糕(即进行单元测试)并保持它(即让 class 2 收到来自 class 1 的异常):(a)我要么 raise 以及 return Class 1 中的 MyException(如果那是甚至可能?),或 (b) 我使用不同的 assert 语句。


编辑 2:感谢一些极好的反馈,我现在明白我最初的错误是错误使用 assertRaises 的结果。它应该被如下使用:

class MyException(Exception):
    pass
class Class1:
    ...

with self.assertRaises(MyException):
    Class1().function_c1(some_input)

但是,单元测试仅在 Class 1 引发 内置 异常时通过,例如 ValueError(因此使用 with self.assertRaises(ValueError):,当然)。我的用户自定义异常 MyException 仍然没有通过单元测试。为什么会这样?

为了捕获异常,您必须 raise 它。如果你 return 它,异常就像任何其他 python 对象一样(并且不会被捕获在 try 块中。

class Class1:
    ''' My nifty class 1. '''
    def __init__(self):
        pass
    def function_c1(self, some_input):
        ''' A function of class 1. '''
        if some_statement(some_input):
            raise MyException('Some error message.')
        return True

为了解决您在下面的评论,为了使用 python 的单元测试模块进行单元测试,您可能会这样做:

with self.assertRaises(MyException):
    Class1().function_c1(...)

如果您停留在 python2.7 之前的环境中,则为:

self.assertRaises(MyException, Class1().function_c1, ...)

不过看在你的份上,我希望你至少可以使用 python2.7 :-).