如何正确使用unit testing的assertRaises()与NoneType对象?

我做了一个简单的testing用例:

def setUp(self): self.testListNone = None def testListSlicing(self): self.assertRaises(TypeError, self.testListNone[:1]) 

我期待testing通过,但我得到例外:

 Traceback (most recent call last): self.assertRaises(TypeError, self.testListNone[:1]) TypeError: 'NoneType' object is unsubscriptable 

我认为assertRaises会通过TypeErrorexception将被提出?

如果您使用python2.7或更高版本,则可以使用assertRaises作为上下文pipe理器的function,并执行以下操作:

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

如果你正在使用python2.6之外的其他方法,直到现在使用unittest2这是unit testing新function的后端口到python2.6,你可以使用上面的代码使其工作。

注意:我是unit testing新function(SkipTest,testing发现…)的忠实粉丝,所以我打算尽可能多地使用unittest2。 我build议做同样的事情,因为python2.6中有很多unit testing。

问题是TypeErrorassertRaises被调用之前被' assertRaises ',因为assertRaises的参数在assertRaises该方法之前需要被评估。 你需要传递一个lambdaexpression式,如:

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

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

 self.assertRaises(TypeError, test_function, args) 

testing函数调用test_function(args)引发TypeError。

self.testListNone[:1]是Python在调用assertRaises方法之前立即计算expression式。 test_functionargs作为独立parameter passing给self.assertRaises的全部原因是允许assertRaisestry...except块中调用test_function(args) ,从而允许assertRaises捕获exception。

既然你已经定义了self.testListNone = None ,并且你需要一个函数来调用,你可以使用operator.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 )从参数。

完整的代码片段如下所示。 它扩展了@ mouad的错误消息的断言(或通常strargs表示),这可能是有用的。

 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))