How to properly use unit-testing's assertRaises() with NoneType objects? [duplicate]

I did a simple test case:

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

and I am expecting test to pass, but I am getting exception:

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

I thought that assertRaises will pass since TypeError exception will be raised?

1

4 Answers

If you are using python2.7 or above you can use the ability of assertRaises to be use as a context manager and do:

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

If you are using python2.6 another way beside the one given until now is to use unittest2 which is a back port of unittest new feature to python2.6, and you can make it work using the code above.

N.B: I'm a big fan of the new feature (SkipTest, test discovery ...) of unittest so I intend to use unittest2 as much as I can. I advise to do the same because there is a lot more than what unittest come with in python2.6 <.

2

The problem is the TypeError gets raised 'before' assertRaises gets called since the arguments to assertRaises need to be evaluated before the method can be called. You need to pass a lambda expression like:

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

The usual way to use assertRaises is to call a function:

self.assertRaises(TypeError, test_function, args) 

to test that the function call test_function(args) raises a TypeError.

The problem with self.testListNone[:1] is that Python evaluates the expression immediately, before the assertRaises method is called. The whole reason why test_function and args is passed as separate arguments to self.assertRaises is to allow assertRaises to call test_function(args) from within a try...except block, allowing assertRaises to catch the exception.

Since you've defined self.testListNone = None, and you need a function to call, you might use operator.itemgetter like this:

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

since

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

is a long-winded way of saying self.testListNone[:1], but which separates the function (operator.itemgetter) from the arguments.

5

Complete snippet would look like the following. It expands @mouad's answer to asserting on error's message (or generally str representation of its args), which may be useful.

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

You Might Also Like