Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Mock Autospec vs Spec

Trying to wrap my head around the difference between Spec and Autospec. They seem to be about the same. Specifically, if you look at mock.patch decorator.

Can someone explain when to use which?

https://docs.python.org/3/library/unittest.mock.html

like image 403
Allen Avatar asked Sep 20 '16 03:09

Allen


People also ask

What is spec in mock Python?

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).

What is the difference between mock and MagicMock?

With Mock you can mock magic methods but you have to define them. MagicMock has "default implementations of most of the magic methods.". If you don't need to test any magic methods, Mock is adequate and doesn't bring a lot of extraneous things into your tests.

What is the difference between mock and patch?

Mock is a type, and patch is a context. So you are going to pass or receive Mock instances as parameters, and apply patch contexts to blocks of code. (Lowercase 'mock' is just the name of the package.) Tests and test classes are often decorated with calls to patch.

What is Side_effect in mock Python?

mock documentation for side_effect : If you pass in an iterable, it is used to retrieve an iterator which must yield a value on every call. This value can either be an exception instance to be raised, or a value to be returned from the call to the mock ( DEFAULT handling is identical to the function case).


1 Answers

spec applies only to the mock instance where it is specified. In particular, if the mocked class a has a method, e.g. method(), then calling that method in the instanciated mock of a will automatically generate and return another mock that is not restricted to any spec. This is where autospec comes in handy, as it recursively defines specs on whatever is called (within the restrictions of the specs defined up to that point).

From the Mock Autospeccing Helper documentation:

If you use a class or instance as the spec for a mock then you can only access attributes on the mock that exist on the real class:

>>> import urllib2
>>> mock = Mock(spec=urllib2.Request)
>>> mock.assret_called_with
Traceback (most recent call last):
...
AttributeError: Mock object has no attribute 'assret_called_with'

The spec only applies to the mock itself, so we still have the same issue with any methods on the mock:

>>> mock.has_data()
<mock.Mock object at 0x...>
>>> mock.has_data.assret_called_with()

Auto-speccing solves this problem.

like image 109
ivavid Avatar answered Sep 27 '22 17:09

ivavid