断言由 @propertyname.setter 生成的异常

Asserting an exception generated by a @propertyname.setter

源代码

我有一些代码要求我调用 属性 setter 来测试 class 的锁定功能是否正常工作([=42= 的某些功能=] 是 async,要求在执行期间设置挂锁布尔值)。如果已为实例设置锁,则 setter 已写入引发 RuntimeError

代码如下:

    @filename.setter
    def filename(self, value):
        if not self.__padlock:
            self.__filename = value
        else:
            self.__events.on_error("data_store is locked.  you should be awaiting safe_unlock if you wish to "
                                  "change the source.")

正如您在此处看到的,如果 self.__padlockTrue,则会引发 RuntimeError。尝试使用 python unittest 断言 setter 时会出现问题。

问题

似乎 unittest 缺少断言 属性 setter 是否引发异常所需的功能。

尝试使用 assertRaises 显然不起作用:

    # Non-working concept
    self.assertRaises(RuntimeError, my_object.filename, "testfile.txt")

问题

如何断言 class 的 属性 setter 将在 python unittest.TestCase 方法中引发给定的异常?

您实际上需要通过赋值调用 setter。这很简单,只要您使用 assertRaises 作为上下文管理器即可。

with self.assertRaises(RuntimeError):
    my_object.filename = "testfile.txt"

如果你不能这样做,你将不得不退回到明确的 try 语句(这变得棘手,因为你需要同时处理 "no exception" 和 "exception other than RuntimeError"分开。

try:
    my_object.filename = "testfile.txt"
except RuntimeError:
    pass
except Exception:
    raise AssertionError("something other than RuntimeError")
else:
    raise AssertionError("no RuntimeError")

或(更多)显式调用 setter:

self.assertRaises(RuntimeError, setattr, myobject, 'filename', 'testfile.txt')

或更糟,显式 调用 setter:

self.assertRaises(RuntimeError, type(myobject).filename.fset, myobject, 'testfile.txt')

换句话说,为上下文管理器欢呼三声!

您可以像这样使用 setattr 方法:

self.assertRaises(ValueError, setattr, p, "name", None)

在上面的例子中,我们将尝试设置 p.name 等于 None 并检查是否有 ValueError 引发。