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

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
Robert Thorne

Robert Thorne

Automotive & Future Transportation Editor

Robert Thorne covers electric vehicle innovations, autonomous driving systems, global mobility trends, and automotive engineering developments.

Share this article
Twitter Facebook Pinterest