How can I override the metaclass of a Python class, with a `unittest.mock.MagicMock` instance instead?
I have a function whose job involves working with the metaclass of an argument:: # lorem.py class Foo(object): pass def quux(existing_class): … metaclass = type(existing_class) new_class = metaclass(…) The unit tests for this function will need to assert that the calls to the metaclass go as expected, *without* actually calling a real class object. To write a unit test for this function, I want to temporarily override the metaclass of some classes in the system with a mock object instead. This will allow, for example, making assertions about how the metaclass was called, and ensuring no unwanted side effects. # test_lorem.py import unittest import unittest.mock import lorem class stub_metaclass(type): def __new__(metaclass, name, bases, namespace): return super().__new__(metaclass, name, bases, namespace) class quux_TestCase(unittest.TestCase): @unittest.mock.patch.object( lorem.Foo, '__class__', side_effect=stub_metaclass) def test_calls_expected_metaclass_with_class_name( self, mock_foo_metaclass, ): lorem.quux(lorem.Foo) mock_foo_metaclass.assert_called_with( 'Foo', unittest.mock.ANY, unittest.mock.ANY) When I try to mock the `__class__` attribute of an existing class, though, I get this error:: File "/usr/lib/python3/dist-packages/mock/mock.py", line 1500, in start result = self.__enter__() File "/usr/lib/python3/dist-packages/mock/mock.py", line 1460, in __enter__ setattr(self.target, self.attribute, new_attr) TypeError: __class__ must be set to a class, not 'MagicMock' object This is telling me that `unittest.mock.patch` is attempting to set the `__class__` attribute temporarily to a `MagicMock` instance, as I want; but Python is refusing that with a `TypeError`. But placing a mock object as the metaclass (the class's `__class__` attribute) is exactly what I'm trying to do, *in order that* the mock object will do all that it does: record calls, pretend valid behaviour, etc. How can I set a mock object in place of the class's `__class__` attribute, in order to instrument my code for testing metaclass operation? -- \ “The problem with television is that the people must sit and | `\ keep their eyes glued on a screen: the average American family | _o__) hasn't time for it.” —_The New York Times_, 1939 | Ben Finney -- https://mail.python.org/mailman/listinfo/python-list