assertRaises not working with Futures

217 views Asked by At

I changed a call to bar which returned synchronously to returning a Future. When the method of bar actually gets executed it raises an ValueError. The unit tests actually ensured that.

Now changing

self.assertRaises(ValueError, foo.bar("/my/invalid/path"))

to

self.assertRaises(ValueError, fut.result())

no longer is a valid assert for some reason.

The whole new code is:

fut = foo.bar("/my/invalid/path")
self.assertIsNotNone(fut)
self.assertRaises(ValueError, fut.result())

The stack trace then is:

"test.py", line 25, in test_load_invalid_res
self.assertRaises(ValueError, fut.result())
File "/usr/lib/python3.5/concurrent/futures/_base.py", line 398, in result
  return self.__get_result()
File "/usr/lib/python3.5/concurrent/futures/_base.py", line 357, in __get_result
  raise self._exception
File "/usr/lib/python3.5/concurrent/futures/thread.py", line 55, in run
  result = self.fn(*self.args, **self.kwargs)
ValueError: Could not find resource in resource path: /my/invalid/path

But the stack trace is actually telling me that there was a ValueError!? Why is it propagading beyond assertRaises?

EDIT:

The following code does not work:

try:
  fut.result()
except ValueError as e:
  pass

What works is e.g.:

try:
  fut.result()
except Exception as e:
  self.assertIsInstance(e, ValueError)
1

There are 1 answers

0
Daniel Roseman On BEST ANSWER

You are calling the method and passing the result to assertRaises. Since the error happens before assertRaises is invoked, it will not catch the exception.

assertRaises takes a callable which it calls itself within a try/except. Your code should be:

self.assertRaises(ValueError, fut.result)

without the calling parens. Alternatively you can use it as a context manager:

with self.assertRaises(ValueError):
    fut.result()