Mock vs MagicMock

PythonMocking

Python Problem Overview


My understanding is that MagicMock is a superset of Mock that automatically does "magic methods" thus seamlessly providing support for lists, iterations and so on... Then what is the reason for plain Mock existing? Isn't that just a stripped down version of MagicMock that can be practically ignored? Does Mock class know any tricks that are not available in MagicMock?

Python Solutions


Solution 1 - Python

What is the reason for plain Mock existing?

Mock's author, Michael Foord, addressed a very similar question at Pycon 2011 (31:00):

> Q: Why was MagicMock made a separate thing rather than just folding the ability into the default mock object? > > A: One reasonable answer is that the way MagicMock works is that it preconfigures all these protocol methods by creating new Mocks and > setting them, so if every new mock created a bunch of new mocks and > set those as protocol methods and then all of those protocol methods > created a bunch more mocks and set them on their protocol methods, > you've got infinite recursion... > > What if you want accessing your mock as a container object to be an > error -- you don't want that to work? If every mock has automatically > got every protocol method, then it becomes much more difficult to do > that. And also, MagicMock does some of this preconfiguring for you, > setting return values that might not be appropriate, so I thought it > would be better to have this convenience one that has everything > preconfigured and available for you, but you can also take a ordinary > mock object and just configure the magic methods you want to exist... > > The simple answer is: just use MagicMock everywhere if that's the > behavior you want.

Solution 2 - Python

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. If you need to test a lot of magic methods MagicMock will save you some time.

Solution 3 - Python

To begin with, MagicMock is a subclass of Mock.

class MagicMock(MagicMixin, Mock)

As a result, MagicMock provides everything that Mock provides and more. Rather than thinking of Mock as being a stripped down version of MagicMock, think of MagicMock as an extended version of Mock. This should address your questions about why Mock exists and what does Mock provide on top of MagicMock.

Secondly, MagicMock provides default implementations of many/most magic methods, whereas Mock doesn't. See here for more information on the magic methods provided.

Some examples of provided magic methods:

>>> 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 these which may not be as intuitive (at least not intuitive to 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 those methods are invoked 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?

The question back to you is: Are you okay with the default magic method implementations? For example, is it okay for mocked_object[1] to not error? Are you okay with any unintended consequences due to the magic method implementations being already there?

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

Solution 4 - Python

This is what python's official documentation says:

> In most of these examples the Mock and MagicMock classes are interchangeable. As the MagicMock is the more capable class it makes a sensible one to use by default.

Solution 5 - Python

I've found another particular case where simple Mock may turn 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

Comparing against ANY can be useful, for example, comparing almost every key between two dictionaries where some value is calculated using a mock.

This will be valid if you're using Mock:


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

while it will raise an AssertionError if you've used MagicMock

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionVladimir IgnatovView Question on Stackoverflow
Solution 1 - PythonRyne EverettView Answer on Stackoverflow
Solution 2 - PythonSean RedmondView Answer on Stackoverflow
Solution 3 - Pythonuser650654View Answer on Stackoverflow
Solution 4 - Pythonuser2916464View Answer on Stackoverflow
Solution 5 - PythonManu ArteroView Answer on Stackoverflow