cpython
cpython copied to clipboard
Consider improving the clarity of unittest.mock.create_autospec
| BPO | 30548 |
|---|---|
| Nosy | @csabella, @mariocj89, @tirkarthi |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee = None
closed_at = None
created_at = <Date 2017-06-02.09:06:21.041>
labels = ['type-feature', 'docs']
title = 'typo in documentation for create_autospec'
updated_at = <Date 2019-10-30.08:35:30.452>
user = 'https://bugs.python.org/ErikBystrm'
bugs.python.org fields:
activity = <Date 2019-10-30.08:35:30.452>
actor = 'Erik Bystr\xc3\xb6m'
assignee = 'docs@python'
closed = False
closed_date = None
closer = None
components = ['Documentation']
creation = <Date 2017-06-02.09:06:21.041>
creator = 'Erik Bystr\xc3\xb6m'
dependencies = []
files = []
hgrepos = []
issue_num = 30548
keywords = []
message_count = 4.0
messages = ['294993', '305609', '334361', '355697']
nosy_count = 5.0
nosy_names = ['docs@python', 'cheryl.sabella', 'mariocj89', 'Erik Bystr\xc3\xb6m', 'xtreak']
pr_nums = []
priority = 'normal'
resolution = None
stage = None
status = 'open'
superseder = None
type = 'enhancement'
url = 'https://bugs.python.org/issue30548'
versions = ['Python 3.6']
"a class" should most probably be replaced by "an instance" in the documentation for create_autospec.
"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."
https://docs.python.org/3/library/unittest.mock.html#unittest.mock.create_autospec
I've always understood instance as a way to say "I am passing this class but I want to force the autospec on the instance"
For example, given
class X:
def __init__(self):
raise
You can do unittest.mock.create_autospec(X, instance=True) to set a spec of the instance rather than the class.
Also quite often you do autospec on a class but you want the interface of the instance. This parameter allows you to do so.
Basically, unittest.mock.create_autospec(X, instance=True) will produce a non callable mock.
I think the docs are correct, maybe misleading
Mario is right that this isn't a typo. Here's a code example to illustrate what he said:
>>> class MyClass:
... a = 3
... def foo(self): pass
...
>>> mock_class = create_autospec(MyClass)
>>> mock_class
<MagicMock spec='MyClass' id='16678696'>
>>> mock_class()
<NonCallableMagicMock name='mock()' spec='MyClass' id='16752016'>
>>> mock_class.foo
<MagicMock name='mock.foo' spec='function' id='16751032'>
>>> mock_instance = create_autospec(MyClass, instance=True)
>>> mock_instance
<NonCallableMagicMock spec='MyClass' id='16757832'>
>>> mock_instance()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'NonCallableMagicMock' object is not callable
>>> mock_instance.foo
<MagicMock name='mock.foo' spec='function' id='16750024'>
As per the docs, the instance object uses the class as the spec and it isn't callable, whereas the mock class is. Would adding this example to the docs help or would a different code example help make this less misleading?
Yes, you're right. I do think the docs are a bit misleading.
Maybe something like this would make it more clear?
"If a class is used as a spec then the returned object will be a mock of that class. When the constructor of the returned mock class is invoked an instance object is returned that has the same spec as a normal instance object would have. By passing instance=True you can directly create a mock instance of the class."
If not, feel free to close this issue.