[TIP] Return different values based on an argument passed to a method

Michael Foord michael at voidspace.org.uk
Mon Mar 5 09:01:43 PST 2012

On 05/03/2012 16:49, Marcin Zajączkowski wrote:
> Dnia 5-03-2012 o godz. 13:41 Michael Foord napisał(a):
>> On 05/03/2012 12:33, Marcin Zajączkowski wrote:
>>> Hi,
>>> Is it possible to simple stub a method's return value when called with
>> an argument (any argument or specific one)?
>>> I tried with:
>>> mock = Mock()
>>> mock.foo(ANY).return_value(False)
>>> but in a debugger I see that in my code mock.foo(<<some_object>>)
>> returns a mock instead of False value. If not the returning value I
>> could use assert_called_with with custom mather, but how to return
>> different value based on an argument?
>> To change the return value of mock.foo you set mock.foo.return_value.
>> mock.foo(ANY).return_value(False)  is fetching the return_value mock got
>> by calling mock.foo - and then calling that mock with False! (You're not
>> setting any return_value at all, you're just making calls.)
>> To have mock.foo return False, do this:
>>       mock.foo.return_value = False
> Thanks for your quick reply! Your solution worked. I am a Java guy and referencing to a method without brackets is very intuitive :).
>> It's not entirely clear to me from your post, but if you want to you can
>> dynamically change the value returned from a call using side_effect.
>>   >>>  from mock import MagicMock
>>   >>>  def side_effect(arg):
>> ...      if arg == 1:
>> ...          return False
>> ...      return True
>> ...
>>   >>>  m = MagicMock()
>>   >>>  m.foo.side_effect = side_effect
>>   >>>  m.foo(1)
>> False
>>   >>>  m.foo(37)
>> True
> It wasn't very precisely in my first mail. A separate function can be useful when you have non trivial logic inside. But maybe it is possible to override the default value returned by mock only for specific (simple) cases in a shorter way?
> For example. Only when foo method called with argument 5 return "you win". Something like (example from Java):
> when(m.foo(5)).willReturn("you win");
> (in other cases return default value)

If you want the "standard" return value, then you can have your 
side_effect return DEFAULT. So this:

 >>> from mock import MagicMock, DEFAULT
 >>> def side_effect(arg):
...      if arg == 5:
...          return 'you win'
...      return DEFAULT
 >>> m = MagicMock()
 >>> m.foo.side_effect = side_effect

All the best,

Michael Foord

> Regards
> Marcin


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 http://www.sqlite.org/different.html

More information about the testing-in-python mailing list