I’m playing around with mock autospecs in Python. Here’s a basic test case where I’m autospecing the Django User class using create_autospec.
from unittest.mock import create_autospec
from django.contrib.auth.models import User
def test_mock_spec():
    user = create_autospec(User, spec_set=True, instance=True, username="batman")
    assert user.username == "batman"
    with pytest.raises(AttributeError):
        create_autospec(User, spec_set=True, x1=1)
    with pytest.raises(AttributeError):
        assert user.x2
The test passes when I set both instance=True and instance=False, so what exactly does this parameter do? What’s its purpose? I’ve seen multiple blog posts set it to True (here and here) so I feel like it’s important.
The documentation says the following but it doesn’t make sense to me:
If a class is used as a spec then the return value of the mock (the instance of the class) will have the same spec. You can use a class as the spec for an instance object by passing instance=True. The returned mock will only be callable if instances of the mock are callable.
Advertisement
Answer
Consider mocking the int class. int is callable, like most classes, so a mock of the int class should also be callable.
On the other hand, consider mocking an int instance. Integers are not callable, so a mock of an integer should also not be callable.
The instance argument lets you control which of these behaviors you get. create_autospec(int, instance=False) returns a callable mock, while create_autospec(int, instance=True) returns a non-callable mock. If you do
m1 = create_autospec(int, instance=False) m2 = create_autospec(int, instance=True) m1() m2()
only the m2() line will raise an exception.