mocking a parent class
<p>I have a <code>Parent</code> class that is inherited by a lot of <code>ChildX</code> classes.</p>

<pre><code>class Parent(object):  # the class that should be mocked
    def __init__(self):
        assert False  # should never happen, because we're supposed to use the mock instead

class Child1(Parent):
    def method_1(self):
        return 3

class MockParent(object):  # this one should replace Parent
    def __init__(self):
        assert True
</code></pre>

<p>I have a test suite to run with pytest, and I want to make sure that, during these tests, everytime a <code>ChildX</code> is instanciated, the instance would call <code>MockParent</code>'s methods instead of the <code>Parent</code>'s ones (I simplified a lot the example above, the <code>__init__</code> method is not the only one concerned).</p>

<p>For the moment, all I've managed to do was to patch every <code>ChildX</code> class one by one:</p>

<pre><code>class FixturePatcher(object):
    def __init__(self, klass):
        self.klass = klass
        self.patcher = None

    def __enter__(self):
        self.patcher = mock.patch.object(self.klass, '__bases__', (MockParent,))
        return self.patcher.__enter__()

    def __exit__(self, *_, **__):
        self.patcher.is_local = True

@pytest.fixture()
def mock_parent_on_child1():
    with FixturePatcher(Child1):
        return Child1()

def test_mock_child1(mock_parent_on_child1):
    assert mock_parent_on_child1.method_1() == 3
</code></pre>

<p>But I have many <code>ChildX</code> classes and sometimes <code>ChildY</code> is instanciated and used inside a method of <code>ChildZ</code>, so I can't patch them all.</p>

<p>I've tried many things to replace <code>Parent</code> by <code>MockParent</code>, but none of them worked. Here are some of my failed attempts:</p>

<pre><code>@mock.patch('src.parent.Parent', MockParent)
def test_mock_parent():
    assert Child1().method_1() == 3  # Parent's __init__ method is still called

@mock.patch('src.parent.Parent.__getattribute__', lambda self, name: MockParent.__getattribute__(self, name))
def test_mock_parent():
    assert Child1().method_1() == 3  # same results here

def test_mock_parent(monkeypatch):
    monkeypatch.setattr('src.parent.Parent', MockParent)
    assert Child1().method_1() == 3  # and still the same here
</code></pre>

<p>Is this even possible? I'm using python2.7 and the up-to-date versions of <code>pytest</code> and <code>mock</code>.</p>

<p>I can't think of a way to replace <code>Parent</code> with <code>MockParent</code> everywhere where it is used, but you could monkeypatch <code>Parent</code>'s methods instead, if that is what you are after:</p>

<pre><code>class Parent(object):
    def my_method(self):
         print 'my method'

class Child(Parent):
    def run(self):
         self.my_method()

child = Child()

child.run()  # prints: my method

### Apply the monkeypatch: ###

def my_method(self):
    print 'something else'

Parent.my_method = my_method

child.run()  # prints: something else
</code></pre>

<p>You could also monkeypatch every method of <code>Parent</code> with a method from <code>MockParent</code>, in the same way. That would be almost the same as if you changed the parent class of everything inherited from <code>Parent</code>.</p>

<p><strong>EDIT:</strong></p>

<p>In fact, you could probably also do exactly what you asked for if you searched for all existing subclasses of <code>Parent</code>, patched them, and monkeypatched the definition if <code>Parent</code> in its module so that future classes are updated as well:</p>

<pre><code>for child_class in Parent.__subclasses__():
    mock.patch.object(child_klass, '__bases__', (MockParent,))

parents_module.Parent = MockParent
</code></pre>

<p>I think this would still miss some special situations, so monkeypatching each method is probably better.</p>

python mocking py.test