Mock parent class __init__ method

26,131

For the first solution, change the return value of the __init__ method to None.

@patch("Derived.Parent.__init__")
def test_init_001(self, mock_parent_init):
    mock_parent_init.return_value = None  # <---
    a = Derived("I am Derived")
    mock_parent_init.assert_called_with("I am Derived")
    self.assertEquals(a.parent_list, ["PARENT", "DERIVED"])

For the second solution, patch Parent.Imported:

@patch("Parent.Imported")  # <---
def test_init_002(self, mock_parent_init):
    a = Derived("I am Derived")
    mock_parent_init.assert_called_with("I am Derived")
    self.assertEquals(a.parent_list, ["PARENT", "DERIVED"])
Share:
26,131
user2944566
Author by

user2944566

Updated on July 05, 2022

Comments

  • user2944566
    user2944566 almost 2 years

    I am trying to write some unittests on a class which is derived from another, but I have some difficulties to mock the parent class init method, which afaik you cannot, so I am looking for suggestion.

    Here an example of how are my classes

    Imported.py

    class Imported():
        def __init__(self, a="I am Imported"):
            print("a:{}".format(a))
    

    Parent.py

    from Imported import Imported
    
    class Parent(object):
    
        parent_list = ["PARENT"]
    
        def __init__(self, a="I am Parent"):
            imported = Imported(a)
    

    Derived.py

    from Parent import Parent
    
    class Derived(Parent):
    
        Parent.parent_list.append("DERIVED")
    

    In my unittests I want to verify that Parent.parent_list == ["PARENT", "DERIVED"] when I instantiate an object from the Derived class, Derived().

    Both of this solution doesn't work

    test_Derived.py

    import unittest
    from mock import patch
    
    from Derived import Derived
    
    
    class test_Derived(unittest.TestCase):
    
        @patch("Derived.Parent.__init__")
        def test_init_001(self, mock_parent_init):
            a = Derived("I am Derived")
            mock_parent_init.assert_called_with("I am Derived")
            self.assertEquals(a.parent_list, ["PARENT", "DERIVED"])
    
        @patch("Derived.Imported.Imported")
        def test_init_002(self, mock_parent_init):
            a = Derived("I am Derived")
            mock_parent_init.assert_called_with("I am Derived")
            self.assertEquals(a.parent_list, ["PARENT", "DERIVED"])
    

    test_init_001 fails with

    TypeError: __init__() should return None, not 'MagicMock'
    

    test_init_002 fails with

    ImportError: No module named Parent.Imported
    

    Any suggestion?

  • Chris
    Chris about 5 years
    I was trying to test that a class was initialized with the right parameters, then a method called on that instance correctly, by mocking __init__ and the method (let's call it foo()). The mocked foo method registered no calls until I set the return value of __init__ to None. (I assume this is because the initialization in the code was broken by the mock of __init__, although setting side_effect to the original __init__ method didn't work - the foo() mock still registered no calls.) Thanks this nearly defeated me!
  • adrz
    adrz almost 3 years
    In your first solution instead of the line mock_parent_init.return_value = None you could specify this thing right in the patch definition, ie. @patch("Derived.Parent.__init__", return_value=None).