Python mock patch argument `new` vs `new_callable`

Question:

From the documentation http://www.voidspace.org.uk/python/mock/patch.html

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

If new is omitted, then the target is replaced with a MagicMock. If patch is used as a decorator and new is omitted, the created mock is passed in as an extra argument to the decorated function. If patch is used as a context manager the created mock is returned by the context manager.

new_callable allows you to specify a different class, or callable
object, that will be called to create the new object. By default
MagicMock is used.

I am trying to understand the differences between the two, and what situation to use new_callable instead of new

Asked By: James Lin

||

Answers:

[EDIT]
In that answer I missed the most important thing that new take an object and new_callable a callable (the factory) as said correctly by @chepner. I don’t remove it because it contains either some useful notes.

By digging the code https://code.google.com/p/mock/source/browse/mock.py#1266 is clear that by new you cannot set the attributes by nominal arguments and use spec or spec_set because it will raise a TypeError exception.

new_callable can be a subclass of NonCallableMock itself and you can use all mock facilities in patch definition.

Sure that behavior is really not documented and also in http://www.voidspace.org.uk/python/mock/changelog.html#version-0-8-0 you can’t find much more than.

New new_callable argument to patch and patch.object allowing you to
pass in a class or callable object (instead of MagicMock) that will be
called to replace the object being patched

Anyway you cannot use something like that to create a YourMockSubclass that have the myobject signature

@patch("mymodule.myobject", new=YourMockSubclass(), spec=myobject)

but in that case you must use new_callable:

@patch("mymodule.myobject", new_callable=YourMockSubclass, spec=myobject)

So you have to use new_callable every time you need a non-MagicMock mock for your mock.

IMHO the only useful use is mocking property.

Answered By: Michele d'Amico

new is an actual object; new_callable is a callable used to create an object. The two cannot be used together (you either specify the replacement or a function to create the replacement; it’s an error to use both.)

>>> foo = 6
>>> with mock.patch('__main__.foo', new=7):
...   print foo
...
7
>>> with mock.patch('__main__.foo', new_callable=lambda : 8):
...   print foo
...
8

When new is mock.DEFAULT, the mock object is a MagicMock instance precisely because the default value of new_callable is MagicMock.

Answered By: chepner
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.