34

I am using Mock 1.0.1 python. In the path function definition there are two optional arguments names spec and spec_set (also auto_spec)

patch(target, new=DEFAULT, spec=None, create=False, spec_set=None, autospec=None, new_callable=None, **kwargs)

I have read through the documentation, but find no explanation of them. Maybe they are terms of testing? It will be nice if someone can give information, thank you.

falsetru
  • 357,413
  • 63
  • 732
  • 636
Hello lad
  • 17,344
  • 46
  • 127
  • 200

2 Answers2

37

unittest.mock in Python 3.x is basically same with mock.

According to the unittest.mock documentation:

spec: This can be either a list of strings or an existing object (a class or instance) that acts as the specification for the mock object. If you pass in an object then a list of strings is formed by calling dir on the object (excluding unsupported magic attributes and methods). Accessing any attribute not in this list will raise an AttributeError.

If spec is an object (rather than a list of strings) then _class_ returns the class of the spec object. This allows mocks to pass isinstance tests.

spec_set: A stricter variant of spec. If used, attempting to set or get an attribute on the mock that isn’t on the object passed as spec_set will raise an AttributeError.


Update Difference between spec and spec_set.

With spec, you can set attribute that is not specified, while with spec_set, it is not allowed to set unspecified attribute.

Example:

>>> from unittest.mock import Mock
>>> class A:
...     def __init__(self, a, b):
...         self.a = a
...         self.b = b
...
>>> aobj = A(1, 2)



>>> m = Mock(spec=aobj)   # spec
>>> m.c   # get -> fail
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python3/3.6.0b4_3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/mock.py", line 582, in __getattr__
    raise AttributeError("Mock object has no attribute %r" % name)
AttributeError: Mock object has no attribute 'c'
>>> m.c = 9  # set -> success
>>> m.c      # get -> success (although c is not in the spec)
9



>>> m = Mock(spec_set=aobj)   # spec_set
>>> m.a
<Mock name='mock.a' id='4544967400'>
>>> m.b
<Mock name='mock.b' id='4545493928'>
>>> m.c   # get -> fail
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python3/3.6.0b4_3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/mock.py", line 582, in __getattr__
    raise AttributeError("Mock object has no attribute %r" % name)
AttributeError: Mock object has no attribute 'c'
>>> m.c = 9  # set -> fail
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python3/3.6.0b4_3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/mock.py", line 688, in __setattr__
    raise AttributeError("Mock object has no attribute '%s'" % name)
AttributeError: Mock object has no attribute 'c'
Piotr Dobrogost
  • 41,292
  • 40
  • 236
  • 366
falsetru
  • 357,413
  • 63
  • 732
  • 636
  • 1
    How are they different then - since it says that using spec will raise an Attribute Error on any attribute which is set/get that isn't in the spec, and spec_set says the same thing. – Tony Suffolk 66 Aug 15 '14 at 10:50
  • @falsetru The OP is asking for clarifications on the documentation, please provide them to answer the question. Note: the documentation is perfectly unclear to me as well, and examples are not really helping. – lajarre Dec 05 '16 at 11:42
  • @TonySuffolk66, with `spec`, you can set the missing attribute. But with `spec_set`, it is not allowed to set missing attribute. – falsetru Dec 05 '16 at 11:53
  • 1
    @lajarre, My bad. Please read above comment. or see this example: https://gist.github.com/falsetru/3ae96d2138f78b103b03daf99fd4d0d2 – falsetru Dec 05 '16 at 11:53
  • @lajarre, I updated the answer to address the issue. Thank you for your feedback. – falsetru Dec 05 '16 at 12:25
  • It is important to note that when using `spec` and then setting some attribute not in the spec you can later access this newly created attribute which is not obvious as it is still not in the spec so according to *Accessing any attribute not in this list will raise an AttributeError* statement from the documentation one could assume it still might not be accessible. – Piotr Dobrogost Aug 26 '20 at 08:15
-1

You can find more info here: http://www.voidspace.org.uk/downloads/mock-1.0.1.pdf

• spec: This can be either a list of strings or an existing object (a class or instance) that acts as the specification for the mock object. If you pass in an object then a list of strings is formed by calling dir on the object (excluding unsupported magic attributes and methods). Accessing any attribute not in this list will raise an AttributeError. If spec is an object (rather than a list of strings) then class returns the class of the spec object. This allows mocks to pass isinstance tests.

• spec_set: A stricter variant of spec. If used, attempting to set or get an attribute on the mock that isn’t on the object passed as spec_set will raise an AttributeError.

Community
  • 1
  • 1
rmcc
  • 743
  • 1
  • 6
  • 14