While having deep dive into how the built-in unittest.mock was designed, I run into these lines in the official source code of mock.py:
class Base(object):
_mock_return_value = DEFAULT
_mock_side_effect = None
def __init__(self, /, *args, **kwargs):
pass
class NonCallableMock(Base):
...
# and later in the init
def _init__ (...):
...
_safe_super(NonCallableMock, self).__init__(
spec, wraps, name, spec_set, parent,
_spec_state
)
What is the role of Base class besides providing common class attributes _mock_return_value and _mock_side_effect as it has just an empty __init__ ?
And why NonCallableMock has to call _safe_super(NonCallableMock, self).__init__(), which I believe is exactly just the empty __init__ method of the Base class ?
Thanks a lot for your answers in advance.
I tried to understand the code but couldn't see the rationale behind the design.
It's for multiple inheritance, which
unittest.mockuses for classes likeclass MagicMock(MagicMixin, Mock):.Despite the name,
superdoesn't mean "call the superclass method". Instead, it finds the next method implementation in a type's method resolution order, which might not come from a parent of the current class when multiple inheritance is involved. When you don't know what methodsuperwill call, you have to be a lot more careful about what arguments you pass to that method.Most of the classes in this class hierarchy forward arguments like
specandwrapsto the next__init__implementation when they call_safe_super(...).__init__(...). Even if none of their ancestors need those arguments, a sibling implementation could still need them. If all of the classes were to forward these arguments, thenobject.__init__would eventually receive those arguments, andobject.__init__would throw an exception.Some class has to handle the job of specifically not passing those arguments to
object.__init__, and that class has to sit at the root of the class hierarchy, right belowobjectitself.Thus, this
Baseclass: a class for all the other classes in this multiple inheritance hierarchy to inherit from, existing almost solely for the purpose of preventingobject.__init__from complaining.