[TIP] mock library comparisons (was Re: Flexmock 0.7.3 released)

Michael Foord fuzzyman at voidspace.org.uk
Sun Feb 27 10:30:41 PST 2011


On 27/02/2011 18:08, Herman Sheremetyev wrote:
> Ah cool, good timing :) I just finished adding your suggestions to my
> own version. I haven't gotten around to doing the context manager bit,
> but I should be able to whip up at least the flexmock and mox versions
> for that later this week.

Cool, ping me when they're done and if you make any other changes to the 
flexmock examples it would be great if you could point them out to me.


> I was also thinking we should maybe start a thread here and get the
> authors or enthusiasts of the other mock libraries to submit their own
> versions for the stuff that I was missing.

We can hope. :-)

Kumar - fudge examples?

All the best,

Michael
> Cheers,
>
> -Herman
>
> On Mon, Feb 28, 2011 at 2:49 AM, Michael Foord
> <fuzzyman at voidspace.org.uk>  wrote:
>> On 24/02/2011 22:10, Michael Foord wrote:
>>> On 24/02/2011 17:11, Herman Sheremetyev wrote:
>>>> On Fri, Feb 25, 2011 at 12:48 AM, Michael Foord
>>>> <fuzzyman at voidspace.org.uk>    wrote:
>>>>> [snip...]
>>>>> If anyone else writes a comparison I'll be very happy to criticise
>>>>> (uh... I
>>>>> mean improve) their examples of using mock. :-)
>>>> I put up a few Mock examples. Comments welcome!
>>>>
>>>> http://has207.github.com/flexmock/compare.html
>>>>
>> Hey Herman,
>>
>> I thought this was such a good idea I've added it to the mock 0.7.0
>> documentation:
>>
>>     http://www.voidspace.org.uk/python/mock/compare.html
>>
>> (With credits to you and the Mox project for the original comparisons.)
>>
>> Feel free to send me any updates. Authors or users of other mock libraries
>> please also send in corrections / comparisons.
>>
>> In this version the mock examples are all in their own "block". This *isn't*
>> to highlight them specially, but its because I've made them all doctests so
>> I can ensure they are kept up to date.
>>
>> The source for this page is available in the mock repo, or online at:
>>
>>     http://www.voidspace.org.uk/python/mock/_sources/compare.txt
>>
>> All the best,
>>
>> Michael Foord
>>
>>> Pretty good. A few minor suggestions and filling in the missing ones (all
>>> assuming mock 0.7.0):
>>>
>>> Simple Mock
>>> Make the last line: my_mock.some_method.assert_called_once_with()
>>>
>>> Creating Partial Mocks
>>> I *think* what you want (instead of using patch) is:
>>>
>>> mock = mock.Mock(spec=SomeObject)
>>>
>>> Ensure calls are made in a specific order:
>>>
>>> mock = mock.Mock(spec=SomeObject)
>>> #mock.method1.return_value = 'first thing' # entirely optional
>>> #mock.method2.return_value = 'second thing'
>>>
>>> mock.method1()
>>> mock.method2()
>>>
>>> assert mock.method_calls == [
>>>     ('method1',)
>>>     ('method2',)
>>> ]
>>>
>>> Raising exceptions (a minor change):
>>>
>>> my_mock.some_method.side_effect = SomeException("message")
>>>
>>>
>>> Override new instances of a class:
>>>
>>> with mock.patch('somemodule.Someclass') as MockClass:
>>>     MockClass.return_value = some_other_object
>>>     assert some_other_object == some_module.SomeClass()
>>>
>>> (alternatively use patch.object(somemodule, 'SomeClass') to patch on the
>>> module as an object instead of by name)
>>>
>>> You can also use patch as a decorator instead of a context manager:
>>>
>>> @patch('somemodule.Someclass')
>>> def my_test_function(MockClass):
>>>     MockClass.return_value = some_other_object
>>>     assert some_other_object == some_module.SomeClass()
>>>
>>> Call the same method multiple times
>>>
>>> mock = Mock()
>>> mock.some_method()
>>> mock.some_method()
>>>
>>> assert mock.some_method.call_count>= 2
>>>
>>> (A lot of information about the calls is available, depending on exactly
>>> what information you want. You don't need to do *anything* to merely *allow*
>>> multiple calls though.)
>>>
>>>
>>> Mock chained methods
>>>
>>> my_mock = mock.Mock()
>>> # if you don't need 'some value' you can leave the default return value in
>>> place
>>> # and assert on equality / identity rather than by value
>>> my_mock.method1.return_value.method2.return_value.method3.return_value =
>>> 'some value'
>>>
>>> assert 'some_value' == my_mock.method1().method2().method3(arg1, arg2)
>>>
>>> method3 = my_mock.method1.return_value.method2.return_value.method3
>>> method3. assert_called_once_with(arg1, arg2)
>>>
>>> These look prettier if you keep around references to the intermediate
>>> mocks rather than chaining it all on one line, but you can do it.
>>>
>>>
>>> How about adding an example of mocking a context manager:
>>>
>>> my_mock = mock.MagicMock()
>>>
>>> with my_mock:
>>>     pass
>>>
>>> my_mock.__enter__.assert_called_with()
>>> my_mock.__exit__.assert_called_with(None, None, None)
>>>
>>> Or even mocking out "open" when used as a context manager:
>>>
>>> First way:
>>>
>>>>>> my_mock = MagicMock()
>>>>>> with patch('__builtin__.open', my_mock):
>>> ...     manager = my_mock.return_value.__enter__.return_value
>>> ...     manager.read.return_value = 'some data'
>>> ...     with open('foo') as h:
>>> ...         data = h.read()
>>> ...
>>>>>> data
>>> 'some data'
>>>>>> my_mock.assert_called_once_with('foo')
>>>
>>> Second way:
>>>
>>>>>> with patch('__builtin__.open') as mock:
>>> ...     mock.return_value.__enter__ = lambda s: s
>>> ...     mock.return_value.__exit__ = Mock()
>>> ...     mock.return_value.read.return_value = 'some data'
>>> ...     with open('foo') as h:
>>> ...         data = h.read()
>>> ...
>>>>>> data
>>> 'some data'
>>>>>> mock.assert_called_once_with('foo')
>>>
>>>> Cheers,
>>>>
>>>> -Herman
>>>
>>
>> --
>> http://www.voidspace.org.uk/
>>
>> 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
>>
>>


-- 
http://www.voidspace.org.uk/

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