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