Reputation: 309
I have a bit of code requiring that I call a property setter to test wether or not locking functionaliy of a class is working (some functions of the class are async
, requiring that a padlock boolean be set during their execution). The setter has been written to raise a RuntimeError
if the lock has been set for the instance.
Here is the code:
@filename.setter
def filename(self, value):
if not self.__padlock:
self.__filename = value
else:
self.__events.on_error("data_store is locked. you should be awaiting safe_unlock if you wish to "
"change the source.")
As you can see here, if self.__padlock
is True
, a RuntimeError
is raised. The issue arises when attempting to assert the setter with python unittest
.
It appears that unittest
lacks functionality needed to assert wether or not a property setter raises an exception.
Attempting to use assertRaises
doesn't obviously work:
# Non-working concept
self.assertRaises(RuntimeError, my_object.filename, "testfile.txt")
How does one assert that a class's property setter will raise a given exception in a python unittest.TestCase
method?
Upvotes: 2
Views: 594
Reputation: 9
You can use the setattr
method like so:
self.assertRaises(ValueError, setattr, p, "name", None)
In the above example, we will try to set p.name
equal to None
and check if there is a ValueError
raised.
Upvotes: 1
Reputation: 531938
You need to actually invoke the setter, via an assignment. This is simple to do, as long as you use assertRaises
as a context manager.
with self.assertRaises(RuntimeError):
my_object.filename = "testfile.txt"
If you couldn't do that, you would have to fall back to an explicit try
statement (which gets tricky, because you need to handle both "no exception" and "exception other than RuntimeError
" separately.
try:
my_object.filename = "testfile.txt"
except RuntimeError:
pass
except Exception:
raise AssertionError("something other than RuntimeError")
else:
raise AssertionError("no RuntimeError")
or (more) explicitly invoke the setter:
self.assertRaises(RuntimeError, setattr, myobject, 'filename', 'testfile.txt')
or worse, explicitly invoke the setter:
self.assertRaises(RuntimeError, type(myobject).filename.fset, myobject, 'testfile.txt')
In other words, three cheers for context managers!
Upvotes: 6