Mock vs MagicMock

My understanding is that MagicMock is a superset of Mock that automatically does “magic methods”, thus easily providing support for lists, iterations, etc ... Then what is the reason for the usual Mock? Isn't that just a stripped down version of MagicMock that you can almost ignore? Does the Mock class know any tricks not available in MagicMock?

+116
python mocking
Jun 19 '13 at 1:49 on
source share
5 answers

What is the reason for the usual mock?

The author’s layout, Michael Foor, addressed a very similar question in Pycon 2011 (31:00) :

Q: Why did MagicMock do a separate thing and not just collapse this ability into a default mock object?

A: One reasonable answer is that the MagicMock method consists in pre-configuring all these protocol methods by creating new Mocks and installing them, so if each new layout created a bunch of new layouts and set them as protocol methods, and then all these protocol methods created a bunch of more mocks and installed them in their protocol methods, you have infinite recursion ...

What if you want to access your layout as a container object as an error - you don’t want this to work? If each layout automatically received each protocol method, then it becomes much more difficult to do that. In addition, MagicMock does some of these presets for you by setting return values ​​that may be unacceptable, so I thought it would be better to have this convenience, which has everything preconfigured and available to you, but you can also take the usual mock object and just set up the magic methods you want to use ...

The simple answer is: just use MagicMock everywhere if the behavior you want.

+89
Apr 11 '14 at
source share

With Mock, you can mock magic methods, but you must define them. MagicMock has "standard implementations of most magic methods." ,

If you don’t need to test any magic methods, Mock is suitable and doesn’t bring many extraneous things into your tests. If you need to test many magic methods, MagicMock will save you time.

+46
Jun 19 '13 at 4:16
source share

For starters, MagicMock is a subclass of Mock .

 class MagicMock(MagicMixin, Mock) 

As a result, MagicMock provides everything that Mock provides, and much more. Instead of thinking that Mock is a stripped-down version of MagicMock, think of MagicMock as an extended version of Mock. This should answer your questions about why Mock exists and what Mock gives in addition to MagicMock.

Secondly, MagicMock provides standard implementations of many / the most magical methods, while Mock does not. See here for more information on the magic methods provided.

Some examples of magic methods provided:

 >>> int(Mock()) TypeError: int() argument must be a string or a number, not 'Mock' >>> int(MagicMock()) 1 >>> len(Mock()) TypeError: object of type 'Mock' has no len() >>> len(MagicMock()) 0 

And those that may not be so intuitive (at least not intuitive for me):

 >>> with MagicMock(): ... print 'hello world' ... hello world >>> MagicMock()[1] <MagicMock name='mock.__getitem__()' id='4385349968'> 

You can “see” the methods added to MagicMock, as these methods are called for the first time:

 >>> magic1 = MagicMock() >>> dir(magic1) ['assert_any_call', 'assert_called_once_with', ...] >>> int(magic1) 1 >>> dir(magic1) ['__int__', 'assert_any_call', 'assert_called_once_with', ...] >>> len(magic1) 0 >>> dir(magic1) ['__int__', '__len__', 'assert_any_call', 'assert_called_once_with', ...] 

So why not use MagicMock all the time?

Question to you: are you ok with default magic method implementations? For example, is this normal for mocked_object[1] so that it doesn't fail? Are you okay with any unforeseen consequences due to the fact that the implementation of the magic method already exists?

If the answer to these questions is yes, then go and use MagicMock. Otherwise, stick with the Mock.

+38
Dec 05
source share

Here's what the official Python documentation says:

In most of these examples, the Mock and MagicMock classes are interchangeable. Since MagicMock is a more capable class, it makes reasonable use by default.

+10
Oct 29 '13 at 23:12
source share

I discovered one more specific case where a simple Mock might be more useful than MagicMock :

 In [1]: from unittest.mock import Mock, MagicMock, ANY In [2]: mock = Mock() In [3]: magic = MagicMock() In [4]: mock.foo == ANY Out[4]: True In [5]: magic.foo == ANY Out[5]: False 

This can be useful, for example, to compare almost every key between two dictionaries, where a certain value is calculated using the layout.

This will be true if you use Mock :

 self.assertDictEqual(my_dict, { 'hello': 'world', 'another': ANY }) 

while it will raise MagicMock AssertionError if you used MagicMock

0
Jul 25 '19 at 13:01
source share



All Articles