How do I make fun of the __init__ superclass to create an attribute containing the object layout for the unit test?

I am trying to write unit test for the __init__ class:

 def __init__(self, buildNum, configFile = "configfile.txt"): super(DevBuild, self).__init__(buildNum, configFile) if configFile == "configfile.txt": self.config.MakeDevBuild() 

The config attribute is set super __init__ . I am using mock and I want the config attribute to be a mock object. However, I could not figure out how to do this. Here is the best I could come up with for the test:

 def test_init(self): with patch('DevBuild.super', create=True) as mock_super: mock_MakeDevBuild = MagicMock() mock_super.return_value.config.MakeDevBuild = mock_MakeDevBuild # Test with manual configuration self.testBuild = DevBuild("42", "devconfigfile.txt") self.assertFalse(mock_MakeDevBuild.called) # Test with automated configuration self.testBuild = DevBuild("42") mock_MakeDevBuild.assert_called_once_with() 

However, this does not work - I get an error message:

 Error Traceback (most recent call last): File "/Users/khagler/Projects/BuildClass/BuildClass/test_devBuild.py", line 17, in test_init self.testBuild = DevBuild("42") File "/Users/khagler/Projects/BuildClass/BuildClass/DevBuild.py", line 39, in __init__ self.config.MakeDevBuild() AttributeError: 'DevBuild' object has no attribute 'config' 

Clearly, I am not setting the config attribute correctly, but I have no idea where exactly I should set it. Or, if it is important, if what I want to do is even possible. Can someone tell me what I need to do to make this work?

+7
source share
1 answer

You cannot mock __init__ by setting it directly - see _ unsupported_magics in mock.py.

What you can do, you can mock __init__ by passing its patch, for example:

 mock_makeDevBuild = MagicMock() def mock_init(self, buildNum, configFile): self.config = MagicMock() self.config.MakeDevBuild = mock_makeDevBuild with patch('DevBuild.SuperDevBuild.__init__', new=mock_init): DevBuild("42") mock_makeDevBuild.assert_called_once_with() 

where SuperDevBuild is the base class of DevBuild.

If you really want to make fun of super() , you can create a class and then bind __init__ to the object manually, for example

 mock_makeDevBuild = MagicMock() def get_mock_super(tp, obj): class mock_super(object): @staticmethod def __init__(buildNum, configFile): obj.config = MagicMock() obj.config.MakeDevBuild = mock_makeDevBuild return mock_super with patch('DevBuild.super', create=True, new=get_mock_super): DevBuild("42") mock_makeDevBuild.assert_called_once_with() 

which works but is pretty ugly.

+16
source

All Articles