hRobert12 / mock

Automatically exported from code.google.com/p/mock
BSD 2-Clause "Simplified" License
0 stars 0 forks source link

Can't pickle MagicMock or Mock #139

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
This is because a MagicMock instance has a custom MagicMock subclass.

{{{
>>> from pickle import dumps
>>> from mock import MagicMock
>>> dumps(MagicMock())
Traceback (most recent call last):
  ...
pickle.PicklingError: Can't pickle <class 'mock.MagicMock'>: it's not the same 
object as mock.MagicMock
}}}

Original issue reported on code.google.com by fuzzyman on 8 Mar 2012 at 6:17

GoogleCodeExporter commented 8 years ago
Because the class for any individual Mock / MagicMock isn't available at the 
top level of the mock module I don't think this can be fixed (fundamental 
pickle limitation).

Original comment by fuzzyman on 9 Mar 2012 at 10:56

GoogleCodeExporter commented 8 years ago
Implementing __reduce__ to return (TopeLevelType, ()) will fix this.

Original comment by fuzzyman on 25 Mar 2012 at 3:47

GoogleCodeExporter commented 8 years ago
Note that just providing __reduce__ is not sufficient.

Objects that have a spec will be pickled as their spec type as pickling uses 
__class__.

_Call objects are not picklable either as they respond to all attribute lookup 
- including __getstate__, __setstate__, __slots__ etc. The same is possibly 
true of sentinel objects.

An alternative approach would be to register a copy_reg function for mocks, 
sentinel and _Call objects. This may or may not mean that mock subclasses need 
separate reg functions.

Original comment by fuzzyman on 14 Apr 2012 at 11:22

GoogleCodeExporter commented 8 years ago
Note:

>>> from pickle import dumps
>>> from mock import MagicMock
>>> m = mock.MagicMock()
>>> m.__class__ = mock.MagicMock
>>> dumps(m)

Works (at least for my use case).

Original comment by k...@google.com on 23 Jan 2013 at 1:50

GoogleCodeExporter commented 8 years ago
it would be awesome to get a fix for this. Otherwise, we have to set return 
values for lots of unimportant parts of our system when they are not under test.

Original comment by kumar.mcmillan on 24 Jul 2013 at 7:53

GoogleCodeExporter commented 8 years ago
Solutions welcomed. Note that setting m.__class__ to MagicMock will break 
certain mock functionality. It's probably enough to make them pickleable though 
and if you're not using the magic methods then maybe the breakage won't affect 
you.

Original comment by fuzzyman on 24 Jul 2013 at 8:07

GoogleCodeExporter commented 8 years ago
I have tried to use a mock in a multiprocessing setting and ran into the 
explained problem. Setting m.__class__ to MagicMock at least breaks the 
m.some_method.called functionality that I would have needed.

Original comment by chw1...@gmail.com on 29 Sep 2014 at 8:56

GoogleCodeExporter commented 8 years ago
I still don't see how it's possible to fix this given the current design of 
Mock. Suggestions welcome!

Original comment by fuzzyman on 10 Oct 2014 at 9:16