Having trouble with Mock and exception side effects
Joshua J. Kugler
joshua at azariah.com
Fri Aug 21 18:27:40 EDT 2020
Hello! I am using Mock to raise an exception in an function as a side effect.
However, Mock is completely redefining the exception itself turning it in to a
MagickMock object, which generates the Python exception
TypeError: catching classes that do not inherit from BaseException is not
allowed
This is my minimal reproducible test case.
# test_case.py
#!/usr/bin/python3
from unittest.mock import patch
import package.module
print('Before patcher start:', package.module.MyException)
patcher = patch('package.module')
mock_hvac = patcher.start()
print('After patcher start:', package.module.MyException)
try:
print('Right before raise:', package.module.MyException)
raise package.module.MyException
except package.module.MyException:
print('Got the exception')
package/__init__.py
# Empty
package/module.py
class MyException(BaseException):
pass
Output:
$ python3.6 --version
Python 3.6.9
$ python3.6 test_case.py
Before patcher start: <class 'package.module.MyException'>
After patcher start: <MagicMock name='module.MyException'
id='140188666285696'>
Right before raise: <MagicMock name='module.MyException' id='140188666285696'>
Traceback (most recent call last):
File "test_case.py", line 21, in <module>
raise package.module.MyException
TypeError: exceptions must derive from BaseException
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "test_case.py", line 23, in <module>
except package.module.MyException:
TypeError: catching classes that do not inherit from BaseException is not
allowed
This is also causing problems for Mock side effects. In this line of code in
mock.py (line 997 for me):
if effect is not None:
if _is_exception(effect):
raise effect
The _is_exception() function checks for an exception via:
return (
isinstance(obj, BaseExceptions) or
isinstance(obj, type) and issubclass(obj, BaseExceptions)
)
Which of course is false, because it's been replaced by a MagicMock object, so
exception side effects aren't properly raised.
According to https://docs.python.org/3.6/library/unittest.mock.html#calling
calling a function after setting the side_effect should raise the Exception,
not a MagicMock object.
https://docs.python.org/3.6/library/unittest.mock.html#unittest.mock.Mock also
says "Alternatively side_effect can be an exception class or instance. In this
case the exception will be raised when the mock is called."
So, this seems to be not behaving as design, or at least not as documented.
This is creating some really serious problems for testing our code, as we want
a function to have a side effect of an Exception, and catch that exception, but
we can do neither when it has been replaced by a MagicMock object.
Thanks for any tips, pointers, or "You're doing it wrong!" education. :)
j
--
Joshua J. Kugler - Fairbanks, Alaska - joshua at azariah.com
Azariah Enterprises - Programming and Website Design
PGP Key: http://pgp.mit.edu/ ID 0x68108cbb73b13b6a
More information about the Python-list
mailing list