Explain Codes LogoExplain Codes Logo

How to properly use unit-testing's assertRaises() with NoneType objects

python
unittest
assertions
testing
Anton ShumikhinbyAnton Shumikhin·Feb 20, 2025
TLDR

To validate exceptions caused by operations on None with assertRaises, your test should call a function that triggers the error. Here is an example:

import unittest class TestNoneOperation(unittest.TestCase): def test_none_method_call_raises(self): with self.assertRaises(AttributeError): none_var = None none_var.invalid_method() # None has no methods. Sounds like my lazy Sundays ;) unittest.main()

In this example, we are checking for an AttributeError when an absent method is called on None.

Properly calling assertRaises

assertRaises() takes in the exception and a callable along with its respective arguments separately. If you pass a callable that has been already triggered, the test framework will catch an unrelated exception. Here's a comparison:

# I hate shooting in the wrong hoop self.assertRaises(ExceptionType, some_function(None)) # Wrong! Early encounter with TypeError exception # Nothing but net! self.assertRaises(ExceptionType, some_function, None) # Better! Callable and args separated

If the arguments themselves are the cause for the TypeError exception, a lambda function can be used for delayed evaluation:

self.assertRaises(ExceptionType, lambda: some_function(None)) # Using lambda for delaying argument evaluation

Asserting specifics of an exception

Using assertRaises() as a context manager allows you to verify the exception type and message:

with self.assertRaises(SomeException) as cm: code_that_raises() # Consider this the Pandora's box of exceptions self.assertEqual('Expected Message', str(cm.exception)) # Whew! Exactly the monster we expected.

This technique is particularly useful when verifying if the correct "NoneType object is not subscriptable" error is raised.

Strategies for obsolete Python versions

  • Python 2.7 and later: Use assertRaises() as a context manager.
  • Python 2.6 and earlier: Use the unittest2 module, which is a backport of the newer unittest features, and brings assertRaises() context manager abilities—like putting jet fuel in a horse cart.

Advanced handling techniques

For more complex situations with assertRaises(), the operator.itemgetter function can be useful. It mimics the behavior of non-subscriptable objects, and helps avoid a TypeError:

import operator self.assertRaises(TypeError, operator.itemgetter(0), None) # Itemgetter is on a None hunt

Fine-tuning your assertRaises

Context is key

Using assertRaises() as a context manager assures you have a robust test that remains stable despite Python version changes. It narrows down the part of your code triggering the exception.

Dodging false positives

Incorrect usage of assertRaises() can lead to false positives. Take care to verify if your exception is raised by the intended part and not because of an unrelated issue.

Leveraging Python 2's compatibility layers

For Python 2.6 or lower, the unittest2 module is like getting a free upgrade for your testing suite.