No, autospeccing cannot mock out attributes set in the
__init__ method of the original class (or in any other method). It can only mock out static attributes, everything that can be found on the class.
Otherwise, the mock would have to create an instance of the class you tried to replace with a mock in the first place, which is not a good idea (think classes that create a lot of real resources when instantiated).
The recursive nature of an auto-specced mock is then limited to those static attributes; if
foo is a class attribute, accessing
Foo().foo will return an auto-specced mock for that attribute. If you have a class
eggs attribute is an object of type
Ham, then the mock of
Spam.eggs will be an auto-specced mock of the
The documentation you read explicitly covers this:
A more serious problem is that it is common for instance attributes to be created in the
__init__method and not to exist on the class at all.
autospeccan’t know about any dynamically created attributes and restricts the api to visible attributes.
You should just set the missing attributes yourself:
@patch('foo.Foo', autospec=TestFoo) def test_patched(self, mock_Foo): mock_Foo.return_value.foo = 'foo' Bar().bar()
or create a subclass of your
Foo class for testing purposes that adds the attribute as a class attribute:
class TestFoo(foo.Foo): foo = 'foo' # class attribute @patch('foo.Foo', autospec=TestFoo) def test_patched(self, mock_Foo): Bar().bar()