[TIP] [Mock] resetting side_effect

Michael Foord michael at voidspace.org.uk
Sun Jan 8 16:40:41 PST 2012

On 8 Jan 2012, at 16:34, Christo Buschek wrote:

> Hey,
> I created for a project of mine that uses some django-orm models the
> excellent Mock library to fake the actual django backend (I could
> prevent any dependency on any django code so far :). I created
> something like an example app that I want to reuse throughout my
> tests. So I do something like that in my test application:
> EditorModel = Mock(name='EditorModel')
> EditorModel.DoesNotExist = Exception
> and in my actual unittests i use code like that:
> from tests.app import EditorModel
> mock_editor = EditorModel.return_value
> EditorModel.objects.get.return_value = mock_editor
> And I repeat that in my different test files/classes. Now this works
> good if I only use return_value, but as soon as I use side_effect I
> created unexpected behaviour, cause I share the same Mock() instance.
> I noticed that if side_effect is set, the mock class uses that,
> otherwise it looks up return_value. So if I use in test A side_effect,
> and in test B I set again a return_value, it will still use the values
> from the previous defined side_effect.
> Is there a way that I can reliable reset my mock instance when using
> side_effect? The docs state clearly that: "Note that reset doesn’t
> clear the return value, side_effect or any child attributes.". Or how
> can I force my mock instance to again use return_value instead of
> side_effect? I hope I could make myself clear,

One option is to not have your mocks persist between tests. It may seem less efficient, but not having test state persist between tests is an important principle of unit testing.

One way to directly achieve what you're asking is to set the side_effect to None on all relevant mocks.

>>> from mock import Mock
>>> m = Mock(side_effect=KeyError, return_value=3)
>>> m()
Traceback (most recent call last):
>>> m.side_effect = None
>>> m()

This restores the return_value. I'll create a feature request for an argument to reset_mock to optionally clear the side_effect as well. It won't make it into 0.8 I'm afraid.

All the best,

Michael Foord

> greetinx
> christo
> _______________________________________________
> testing-in-python mailing list
> testing-in-python at lists.idyll.org
> http://lists.idyll.org/listinfo/testing-in-python


May you do good and not evil
May you find forgiveness for yourself and forgive others
May you share freely, never taking more than you give.
-- the sqlite blessing 

More information about the testing-in-python mailing list