Having trouble with Mock and exception side effects
Kushal Kumaran
kushal at locationd.net
Fri Aug 21 23:52:38 EDT 2020
You could attempt something like what is mentioned in
https://docs.python.org/3/library/unittest.mock-examples.html#partial-mocking
See below.
"Joshua J. Kugler" <joshua at azariah.com> writes:
> 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)
>
orig_exception = package.module.MyException
> patcher = patch('package.module')
> mock_hvac = patcher.start()
>
> print('After patcher start:', package.module.MyException)
package.module.MyException = orig_exception
print('After exception restore:', 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.
>
It will raise what you tell it to raise. You have to maintain a
reference to the original Exception object, so you can continue to use
it after mocking.
> 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. :)
>
Your problem is entirely described by the fact that you point out: the
package.module.MyException name has been pointed to a MagicMock object.
If you don't want that, you have to restore the name to what you want.
--
regards,
kushal
More information about the Python-list
mailing list