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

时间:2016-02-18 14:29:25

标签: python class exception-handling message-passing

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

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会返回' True '不管Class 1是否返回异常?

编辑1 :在上面的示例中,我故意选择了return而不是raise异常,以便将类1应用于单元测试。

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

鉴于我对Python的理解不完全,我认为只有两种方法可以吃蛋糕(即进行单元测试)并保留它(即,让第2类接受第1类的例外):( a)I是raise 以及 return类1中的MyException(如果可能的话?),或者(b)我使用不同的assert语句。< / p>

编辑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 仍然没有通过单元测试。为什么会这样?

1 个答案:

答案 0 :(得分:1)

为了能够捕获异常,您必须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的unittest模块进行单元测试,你可能会做这样的事情:

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

如果您陷入pre-python2.7环境,那将是:

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

但是为了你的缘故,我希望你至少可以使用python2.7: - 。