如何对 NoneType 对象正确使用单元测试的 assertRaises () ?

我做了一个简单的测试案例:

def setUp(self):


self.testListNone = None


def testListSlicing(self):


self.assertRaises(TypeError, self.testListNone[:1])

我希望能通过考试,但是我得到了例外:

Traceback (most recent call last):


self.assertRaises(TypeError, self.testListNone[:1])


TypeError: 'NoneType' object is unsubscriptable

我认为 assertRaises 将通过,因为 TypeError 异常将通过 被提高

171856 次浏览

通常使用 assertRaises的方法是调用一个函数:

self.assertRaises(TypeError, test_function, args)

来测试函数调用 test _ function (args)是否引发 TypeError。

self.testListNone[:1]的问题在于 Python 会在调用 assertRaises方法之前立即计算表达式。将 test_functionargs作为单独的参数传递给 self.assertRaises的全部原因是允许 assertRaisestry...except块内调用 test_function(args),允许 assertRaises捕获异常。

既然已经定义了 self.testListNone = None,并且需要一个函数来调用,那么可以像下面这样使用 操作员 itemgetter:

import operator
self.assertRaises(TypeError, operator.itemgetter, (self.testListNone,slice(None,1)))

从那以后

operator.itemgetter(self.testListNone,slice(None,1))

是一种冗长的表示 self.testListNone[:1]的方式,但它将函数(operator.itemgetter)与参数分开。

问题是 TypeErrorassertRaises被调用之前被提出,因为 assertRaises的参数需要在方法被调用之前被计算。您需要传递如下 lambda表达式:

self.assertRaises(TypeError, lambda: self.testListNone[:1])

如果您正在使用 python2.7或更高版本,您可以使用 断言提升作为上下文管理器的能力,并执行以下操作:

with self.assertRaises(TypeError):
self.testListNone[:1]

如果您正在使用 python2.6,除了之前给出的方法之外,另一种方法是使用 单元测试2,它是 python2.6的 unittest 新特性的后端口,您可以使用上面的代码使其工作。

注意: 我非常喜欢 unittest 的新特性(SkipTest,测试发现...) ,所以我打算尽可能多地使用 unittest2。我建议也这样做,因为 python2.6中的 unittest 远远不止这些。

完整的代码片段如下所示。它将@mouad 的答案扩展为对错误消息(或通常是对其 argsstr表示)进行断言,这可能很有用。

from unittest import TestCase




class TestNoneTypeError(TestCase):


def setUp(self):
self.testListNone = None


def testListSlicing(self):
with self.assertRaises(TypeError) as ctx:
self.testListNone[:1]
self.assertEqual("'NoneType' object is not subscriptable", str(ctx.exception))