14

Given:

def test_to_check_exception_is_thrown(self):
    # Arrange
    c = Class()
    # Act and Assert
    self.assertRaises(NameError, c.do_something)

If do_something throws an exception the test passes.

But I have a property, and when I replace c.do_something with c.name = "Name" I get an error about my Test Module not being imported and Eclipse highlights the equals symbol.

How do I test a property throws an exception?

Edit:

setattr and getattr are new to me. They've certainly helped in this case, thanks.

danio
  • 8,548
  • 6
  • 47
  • 55
Finglas
  • 15,518
  • 10
  • 56
  • 89

5 Answers5

18

Since Python 2.7 and 3.1 assertRaises() can be used as a context manager. See here for Python 2 and here for Python3.

So you can write your test with the with instruction like this:

def test_to_check_exception_is_thrown(self):
    c = Class()
    with self.assertRaises(NameError):
        c.name = "Name"
Raphael Ahrens
  • 953
  • 15
  • 29
17

assertRaises expects a callable object. You can create a function and pass it:

obj = Class()
def setNameTest():
    obj.name = "Name"        
self.assertRaises(NameError, setNameTest)

Another possibility is to use setattr:

self.assertRaises(NameError, setattr, obj, "name", "Name")

Your original code raises a syntax error because assignment is a statement and cannot be placed inside an expression.

danio
  • 8,548
  • 6
  • 47
  • 55
interjay
  • 107,303
  • 21
  • 270
  • 254
  • 2
    Since python 2.7+ should checkout @RaphaelAhrens answer below. It is a lot more pythonic http://stackoverflow.com/a/23650764/601245 – Matt Seymour Sep 09 '16 at 14:55
8

The second argument to assertRaises should be a callable.

An assignment statement (ie. class.name = "Name") is not a callable so it will not work. Use setattr to perform the assignment like so

self.assertRaises(NameError, setattr, myclass, "name", "Name")

Also, you can't assign to class since it's a keyword.

danio
  • 8,548
  • 6
  • 47
  • 55
Noufal Ibrahim
  • 71,383
  • 13
  • 135
  • 169
2

As @interjay stated, it is expecting a callable, but you don't really need to define a named function for this. A lambda will do it:

self.assertRaises(SomeException, lambda: my_instance.some_property)
Luis Sieira
  • 29,926
  • 3
  • 31
  • 53
-1

You're getting an error because it's a syntax error in Python to have an assignment inside another expression. For example:

>>> print(foo = 'bar')
------------------------------------------------------------
   File "<ipython console>", line 1
     print(foo = 'bar')
               ^
SyntaxError: invalid syntax

But doing it in two steps works fine:

>>> foo = 'bar'
>>> print(foo)
bar

To test that a property throws an exception, use a try block:

try:
   object.property = 'error'
except ExpectedError:
   test_passes()
else:
   test_fails()
samtregar
  • 6,888
  • 3
  • 21
  • 17