Python - 测试属性是否会抛出异常

14

假设有:

def test_to_check_exception_is_thrown(self):
    # Arrange
    c = Class()
    # Act and Assert
    self.assertRaises(NameError, c.do_something)
如果do_something抛出异常,测试就会通过。
但是我有一个属性,当我用c.name =“Name”替换c.do_something时,我会得到一个关于我的测试模块未被导入的错误,并且Eclipse会突出显示等号符号。
如何测试属性是否抛出异常?
编辑: setattrgetattr对我来说是新的。它们在这种情况下肯定有帮助,谢谢。
5个回答

18

自 Python 2.7 和 3.1 版本开始,assertRaises() 可以作为上下文管理器使用。请参见 Python 2 的这里Python 3 的这里

因此,您可以像以下这样使用 with 指令编写测试:

def test_to_check_exception_is_thrown(self):
    c = Class()
    with self.assertRaises(NameError):
        c.name = "Name"

17

assertRaises 需要一个可调用对象。你可以创建一个函数并将其传递:

obj = Class()
def setNameTest():
    obj.name = "Name"        
self.assertRaises(NameError, setNameTest)

另一种可能性是使用 setattr

self.assertRaises(NameError, setattr, obj, "name", "Name")

你的原始代码会引发语法错误,因为赋值是一种语句,不能放置在表达式内。


2
自从Python 2.7+以后,应该查看下面@RaphaelAhrens的答案。它更符合Pythonic的风格。https://dev59.com/m3I95IYBdhLWcg3w-DL0#23650764 - Matt Seymour

8

assertRaises的第二个参数应该是可调用的

赋值语句(例如class.name = "Name")不是可调用的,因此它不起作用。使用setattr执行赋值操作,如下所示:

self.assertRaises(NameError, setattr, myclass, "name", "Name")

此外,由于class是一个关键字,因此您无法对其进行赋值。

2

正如@interjay所说,它需要一个可调用对象,但你其实不需要为此定义一个命名函数。使用lambda表达式即可:

self.assertRaises(SomeException, lambda: my_instance.some_property)

能否解释一下为什么这个值得负评?可能我忽略了一些副作用。谢谢。 - Luis Sieira

-1
你遇到错误是因为在Python中,在另一个表达式内部进行赋值是语法错误。例如:
>>> print(foo = 'bar')
------------------------------------------------------------
   File "<ipython console>", line 1
     print(foo = 'bar')
               ^
SyntaxError: invalid syntax

但是分两步完成可以正常工作:

>>> foo = 'bar'
>>> print(foo)
bar

为了测试一个属性是否会抛出异常,可以使用 try 块:

try:
   object.property = 'error'
except ExpectedError:
   test_passes()
else:
   test_fails()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接