Reputation: 8658
I have a package that has a dependency that is not pip
installable. In order to be able to build the documentation, I am trying to mock the non-installable package using MagicMock
.
However I stumbled across a problem with multiple inheritance: when one of the parent classes is a mock class I get:
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses
The following example illustrates the issue:
file: class_a.py
class A:
pass
file: code.py
from class_a import A
class B:
pass
class C(A, B):
pass
file: test.py
import sys
from unittest import mock
# inspired by https://stackoverflow.com/a/37363830/1860757
MOCK_MODULES = ['class_a', ]
sys.modules.update((mod_name, mock.MagicMock()) for mod_name in MOCK_MODULES)
import code
code.C()
If I run python3 test.py
I get the above exception.
If I comment the line starting with sys.modules.update
, it all behaves as expected.
Is there a way to mock modules or classes such that multiple inheritance continue working?
Upvotes: 2
Views: 794
Reputation: 26
I know this is and old post but anyway. Looks like these lines are not necessary because the module class_a exists you don't need to mock it:
# MOCK_MODULES = ['class_a', ]
# sys.modules.update((mod_name, mock.MagicMock()) for mod_name in MOCK_MODULES)
Upvotes: 0
Reputation: 8658
I did some more research and tests and I have found a way, so I answer my own question for completeness. I don't know if it is a solution or a workaround. However the trick is to explicitly mock classes involved in multiple inheritance. The following does work as expected:
import sys
from unittest import mock
class _A:
pass
MOCK_MODULES = ['class_a', ]
sys.modules.update((mod_name, mock.MagicMock()) for mod_name in MOCK_MODULES)
patcher = mock.patch('class_a.A', new=_A)
patcher.start()
import code
code.C()
patcher.stop()
If anyone in the future finds a new/better way, ping me and I will re-evaluate the accepted answer.
Upvotes: 4