michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: Mock Library Comparison — Mock 1.0.0 documentation michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0:
michael@0:
michael@0:
michael@0:
michael@0: michael@0:
michael@0:

Mock Library Comparison

michael@0:

A side-by-side comparison of how to accomplish some basic tasks with mock and michael@0: some other popular Python mocking libraries and frameworks.

michael@0:

These are:

michael@0: michael@0:

Popular python mocking frameworks not yet represented here include michael@0: MiniMock.

michael@0:

pMock (last release 2004 and doesn’t import michael@0: in recent versions of Python) and michael@0: python-mock (last release 2005) are michael@0: intentionally omitted.

michael@0:
michael@0:

Note

michael@0:

A more up to date, and tested for all mock libraries (only the mock michael@0: examples on this page can be executed as doctests) version of this michael@0: comparison is maintained by Gary Bernhardt:

michael@0: michael@0:
michael@0:

This comparison is by no means complete, and also may not be fully idiomatic michael@0: for all the libraries represented. Please contribute corrections, missing michael@0: comparisons, or comparisons for additional libraries to the mock issue michael@0: tracker.

michael@0:

This comparison page was originally created by the Mox project and then extended for michael@0: flexmock and mock by michael@0: Herman Sheremetyev. Dingus examples written by Gary Bernhadt. fudge examples michael@0: provided by Kumar McMillan.

michael@0:
michael@0:

Note

michael@0:

The examples tasks here were originally created by Mox which is a mocking michael@0: framework rather than a library like mock. The tasks shown naturally michael@0: exemplify tasks that frameworks are good at and not the ones they make michael@0: harder. In particular you can take a Mock or MagicMock object and use michael@0: it in any way you want with no up-front configuration. The same is also michael@0: true for Dingus.

michael@0:

The examples for mock here assume version 0.7.0.

michael@0:
michael@0:
michael@0:

Simple fake object

michael@0:
>>> # mock
michael@0: >>> my_mock = mock.Mock()
michael@0: >>> my_mock.some_method.return_value = "calculated value"
michael@0: >>> my_mock.some_attribute = "value"
michael@0: >>> assertEqual("calculated value", my_mock.some_method())
michael@0: >>> assertEqual("value", my_mock.some_attribute)
michael@0: 
michael@0:
michael@0:
# Flexmock
michael@0: mock = flexmock(some_method=lambda: "calculated value", some_attribute="value")
michael@0: assertEqual("calculated value", mock.some_method())
michael@0: assertEqual("value", mock.some_attribute)
michael@0: 
michael@0: # Mox
michael@0: mock = mox.MockAnything()
michael@0: mock.some_method().AndReturn("calculated value")
michael@0: mock.some_attribute = "value"
michael@0: mox.Replay(mock)
michael@0: assertEqual("calculated value", mock.some_method())
michael@0: assertEqual("value", mock.some_attribute)
michael@0: 
michael@0: # Mocker
michael@0: mock = mocker.mock()
michael@0: mock.some_method()
michael@0: mocker.result("calculated value")
michael@0: mocker.replay()
michael@0: mock.some_attribute = "value"
michael@0: assertEqual("calculated value", mock.some_method())
michael@0: assertEqual("value", mock.some_attribute)
michael@0: 
michael@0:
michael@0:
>>> # Dingus
michael@0: >>> my_dingus = dingus.Dingus(some_attribute="value",
michael@0: ...                           some_method__returns="calculated value")
michael@0: >>> assertEqual("calculated value", my_dingus.some_method())
michael@0: >>> assertEqual("value", my_dingus.some_attribute)
michael@0: 
michael@0:
michael@0:
>>> # fudge
michael@0: >>> my_fake = (fudge.Fake()
michael@0: ...            .provides('some_method')
michael@0: ...            .returns("calculated value")
michael@0: ...            .has_attr(some_attribute="value"))
michael@0: ...
michael@0: >>> assertEqual("calculated value", my_fake.some_method())
michael@0: >>> assertEqual("value", my_fake.some_attribute)
michael@0: 
michael@0:
michael@0:
michael@0:
michael@0:

Simple mock

michael@0:
>>> # mock
michael@0: >>> my_mock = mock.Mock()
michael@0: >>> my_mock.some_method.return_value = "value"
michael@0: >>> assertEqual("value", my_mock.some_method())
michael@0: >>> my_mock.some_method.assert_called_once_with()
michael@0: 
michael@0:
michael@0:
# Flexmock
michael@0: mock = flexmock()
michael@0: mock.should_receive("some_method").and_return("value").once
michael@0: assertEqual("value", mock.some_method())
michael@0: 
michael@0: # Mox
michael@0: mock = mox.MockAnything()
michael@0: mock.some_method().AndReturn("value")
michael@0: mox.Replay(mock)
michael@0: assertEqual("value", mock.some_method())
michael@0: mox.Verify(mock)
michael@0: 
michael@0: # Mocker
michael@0: mock = mocker.mock()
michael@0: mock.some_method()
michael@0: mocker.result("value")
michael@0: mocker.replay()
michael@0: assertEqual("value", mock.some_method())
michael@0: mocker.verify()
michael@0: 
michael@0:
michael@0:
>>> # Dingus
michael@0: >>> my_dingus = dingus.Dingus(some_method__returns="value")
michael@0: >>> assertEqual("value", my_dingus.some_method())
michael@0: >>> assert my_dingus.some_method.calls().once()
michael@0: 
michael@0:
michael@0:
>>> # fudge
michael@0: >>> @fudge.test
michael@0: ... def test():
michael@0: ...     my_fake = (fudge.Fake()
michael@0: ...                .expects('some_method')
michael@0: ...                .returns("value")
michael@0: ...                .times_called(1))
michael@0: ...
michael@0: >>> test()
michael@0: Traceback (most recent call last):
michael@0: ...
michael@0: AssertionError: fake:my_fake.some_method() was not called
michael@0: 
michael@0:
michael@0:
michael@0:
michael@0:

Creating partial mocks

michael@0:
>>> # mock
michael@0: >>> SomeObject.some_method = mock.Mock(return_value='value')
michael@0: >>> assertEqual("value", SomeObject.some_method())
michael@0: 
michael@0:
michael@0:
# Flexmock
michael@0: flexmock(SomeObject).should_receive("some_method").and_return('value')
michael@0: assertEqual("value", mock.some_method())
michael@0: 
michael@0: # Mox
michael@0: mock = mox.MockObject(SomeObject)
michael@0: mock.some_method().AndReturn("value")
michael@0: mox.Replay(mock)
michael@0: assertEqual("value", mock.some_method())
michael@0: mox.Verify(mock)
michael@0: 
michael@0: # Mocker
michael@0: mock = mocker.mock(SomeObject)
michael@0: mock.Get()
michael@0: mocker.result("value")
michael@0: mocker.replay()
michael@0: assertEqual("value", mock.some_method())
michael@0: mocker.verify()
michael@0: 
michael@0:
michael@0:
>>> # Dingus
michael@0: >>> object = SomeObject
michael@0: >>> object.some_method = dingus.Dingus(return_value="value")
michael@0: >>> assertEqual("value", object.some_method())
michael@0: 
michael@0:
michael@0:
>>> # fudge
michael@0: >>> fake = fudge.Fake().is_callable().returns("<fudge-value>")
michael@0: >>> with fudge.patched_context(SomeObject, 'some_method', fake):
michael@0: ...     s = SomeObject()
michael@0: ...     assertEqual("<fudge-value>", s.some_method())
michael@0: ...
michael@0: 
michael@0:
michael@0:
michael@0:
michael@0:

Ensure calls are made in specific order

michael@0:
>>> # mock
michael@0: >>> my_mock = mock.Mock(spec=SomeObject)
michael@0: >>> my_mock.method1()
michael@0: <Mock name='mock.method1()' id='...'>
michael@0: >>> my_mock.method2()
michael@0: <Mock name='mock.method2()' id='...'>
michael@0: >>> assertEqual(my_mock.mock_calls, [call.method1(), call.method2()])
michael@0: 
michael@0:
michael@0:
# Flexmock
michael@0: mock = flexmock(SomeObject)
michael@0: mock.should_receive('method1').once.ordered.and_return('first thing')
michael@0: mock.should_receive('method2').once.ordered.and_return('second thing')
michael@0: 
michael@0: # Mox
michael@0: mock = mox.MockObject(SomeObject)
michael@0: mock.method1().AndReturn('first thing')
michael@0: mock.method2().AndReturn('second thing')
michael@0: mox.Replay(mock)
michael@0: mox.Verify(mock)
michael@0: 
michael@0: # Mocker
michael@0: mock = mocker.mock()
michael@0: with mocker.order():
michael@0:     mock.method1()
michael@0:     mocker.result('first thing')
michael@0:     mock.method2()
michael@0:     mocker.result('second thing')
michael@0:     mocker.replay()
michael@0:     mocker.verify()
michael@0: 
michael@0:
michael@0:
>>> # Dingus
michael@0: >>> my_dingus = dingus.Dingus()
michael@0: >>> my_dingus.method1()
michael@0: <Dingus ...>
michael@0: >>> my_dingus.method2()
michael@0: <Dingus ...>
michael@0: >>> assertEqual(['method1', 'method2'], [call.name for call in my_dingus.calls])
michael@0: 
michael@0:
michael@0:
>>> # fudge
michael@0: >>> @fudge.test
michael@0: ... def test():
michael@0: ...     my_fake = (fudge.Fake()
michael@0: ...                .remember_order()
michael@0: ...                .expects('method1')
michael@0: ...                .expects('method2'))
michael@0: ...     my_fake.method2()
michael@0: ...     my_fake.method1()
michael@0: ...
michael@0: >>> test()
michael@0: Traceback (most recent call last):
michael@0: ...
michael@0: AssertionError: Call #1 was fake:my_fake.method2(); Expected: #1 fake:my_fake.method1(), #2 fake:my_fake.method2(), end
michael@0: 
michael@0:
michael@0:
michael@0:
michael@0:

Raising exceptions

michael@0:
>>> # mock
michael@0: >>> my_mock = mock.Mock()
michael@0: >>> my_mock.some_method.side_effect = SomeException("message")
michael@0: >>> assertRaises(SomeException, my_mock.some_method)
michael@0: 
michael@0:
michael@0:
# Flexmock
michael@0: mock = flexmock()
michael@0: mock.should_receive("some_method").and_raise(SomeException("message"))
michael@0: assertRaises(SomeException, mock.some_method)
michael@0: 
michael@0: # Mox
michael@0: mock = mox.MockAnything()
michael@0: mock.some_method().AndRaise(SomeException("message"))
michael@0: mox.Replay(mock)
michael@0: assertRaises(SomeException, mock.some_method)
michael@0: mox.Verify(mock)
michael@0: 
michael@0: # Mocker
michael@0: mock = mocker.mock()
michael@0: mock.some_method()
michael@0: mocker.throw(SomeException("message"))
michael@0: mocker.replay()
michael@0: assertRaises(SomeException, mock.some_method)
michael@0: mocker.verify()
michael@0: 
michael@0:
michael@0:
>>> # Dingus
michael@0: >>> my_dingus = dingus.Dingus()
michael@0: >>> my_dingus.some_method = dingus.exception_raiser(SomeException)
michael@0: >>> assertRaises(SomeException, my_dingus.some_method)
michael@0: 
michael@0:
michael@0:
>>> # fudge
michael@0: >>> my_fake = (fudge.Fake()
michael@0: ...            .is_callable()
michael@0: ...            .raises(SomeException("message")))
michael@0: ...
michael@0: >>> my_fake()
michael@0: Traceback (most recent call last):
michael@0: ...
michael@0: SomeException: message
michael@0: 
michael@0:
michael@0:
michael@0:
michael@0:

Override new instances of a class

michael@0:
>>> # mock
michael@0: >>> with mock.patch('somemodule.Someclass') as MockClass:
michael@0: ...     MockClass.return_value = some_other_object
michael@0: ...     assertEqual(some_other_object, somemodule.Someclass())
michael@0: ...
michael@0: 
michael@0:
michael@0:
# Flexmock
michael@0: flexmock(some_module.SomeClass, new_instances=some_other_object)
michael@0: assertEqual(some_other_object, some_module.SomeClass())
michael@0: 
michael@0: # Mox
michael@0: # (you will probably have mox.Mox() available as self.mox in a real test)
michael@0: mox.Mox().StubOutWithMock(some_module, 'SomeClass', use_mock_anything=True)
michael@0: some_module.SomeClass().AndReturn(some_other_object)
michael@0: mox.ReplayAll()
michael@0: assertEqual(some_other_object, some_module.SomeClass())
michael@0: 
michael@0: # Mocker
michael@0: instance = mocker.mock()
michael@0: klass = mocker.replace(SomeClass, spec=None)
michael@0: klass('expected', 'args')
michael@0: mocker.result(instance)
michael@0: 
michael@0:
michael@0:
>>> # Dingus
michael@0: >>> MockClass = dingus.Dingus(return_value=some_other_object)
michael@0: >>> with dingus.patch('somemodule.SomeClass', MockClass):
michael@0: ...     assertEqual(some_other_object, somemodule.SomeClass())
michael@0: ...
michael@0: 
michael@0:
michael@0:
>>> # fudge
michael@0: >>> @fudge.patch('somemodule.SomeClass')
michael@0: ... def test(FakeClass):
michael@0: ...     FakeClass.is_callable().returns(some_other_object)
michael@0: ...     assertEqual(some_other_object, somemodule.SomeClass())
michael@0: ...
michael@0: >>> test()
michael@0: 
michael@0:
michael@0:
michael@0:
michael@0:

Call the same method multiple times

michael@0:
michael@0:

Note

michael@0:

You don’t need to do any configuration to call mock.Mock() methods michael@0: multiple times. Attributes like call_count, call_args_list and michael@0: method_calls provide various different ways of making assertions about michael@0: how the mock was used.

michael@0:
michael@0:
>>> # mock
michael@0: >>> my_mock = mock.Mock()
michael@0: >>> my_mock.some_method()
michael@0: <Mock name='mock.some_method()' id='...'>
michael@0: >>> my_mock.some_method()
michael@0: <Mock name='mock.some_method()' id='...'>
michael@0: >>> assert my_mock.some_method.call_count >= 2
michael@0: 
michael@0:
michael@0:
# Flexmock # (verifies that the method gets called at least twice)
michael@0: flexmock(some_object).should_receive('some_method').at_least.twice
michael@0: 
michael@0: # Mox
michael@0: # (does not support variable number of calls, so you need to create a new entry for each explicit call)
michael@0: mock = mox.MockObject(some_object)
michael@0: mock.some_method(mox.IgnoreArg(), mox.IgnoreArg())
michael@0: mock.some_method(mox.IgnoreArg(), mox.IgnoreArg())
michael@0: mox.Replay(mock)
michael@0: mox.Verify(mock)
michael@0: 
michael@0: # Mocker
michael@0: # (TODO)
michael@0: 
michael@0:
michael@0:
>>> # Dingus
michael@0: >>> my_dingus = dingus.Dingus()
michael@0: >>> my_dingus.some_method()
michael@0: <Dingus ...>
michael@0: >>> my_dingus.some_method()
michael@0: <Dingus ...>
michael@0: >>> assert len(my_dingus.calls('some_method')) == 2
michael@0: 
michael@0:
michael@0:
>>> # fudge
michael@0: >>> @fudge.test
michael@0: ... def test():
michael@0: ...     my_fake = fudge.Fake().expects('some_method').times_called(2)
michael@0: ...     my_fake.some_method()
michael@0: ...
michael@0: >>> test()
michael@0: Traceback (most recent call last):
michael@0: ...
michael@0: AssertionError: fake:my_fake.some_method() was called 1 time(s). Expected 2.
michael@0: 
michael@0:
michael@0:
michael@0:
michael@0:

Mock chained methods

michael@0:
>>> # mock
michael@0: >>> my_mock = mock.Mock()
michael@0: >>> method3 = my_mock.method1.return_value.method2.return_value.method3
michael@0: >>> method3.return_value = 'some value'
michael@0: >>> assertEqual('some value', my_mock.method1().method2().method3(1, 2))
michael@0: >>> method3.assert_called_once_with(1, 2)
michael@0: 
michael@0:
michael@0:
# Flexmock
michael@0: # (intermediate method calls are automatically assigned to temporary fake objects
michael@0: # and can be called with any arguments)
michael@0: flexmock(some_object).should_receive(
michael@0:     'method1.method2.method3'
michael@0: ).with_args(arg1, arg2).and_return('some value')
michael@0: assertEqual('some_value', some_object.method1().method2().method3(arg1, arg2))
michael@0: 
michael@0:
michael@0:
# Mox
michael@0: mock = mox.MockObject(some_object)
michael@0: mock2 = mox.MockAnything()
michael@0: mock3 = mox.MockAnything()
michael@0: mock.method1().AndReturn(mock1)
michael@0: mock2.method2().AndReturn(mock2)
michael@0: mock3.method3(arg1, arg2).AndReturn('some_value')
michael@0: self.mox.ReplayAll()
michael@0: assertEqual("some_value", some_object.method1().method2().method3(arg1, arg2))
michael@0: self.mox.VerifyAll()
michael@0: 
michael@0: # Mocker
michael@0: # (TODO)
michael@0: 
michael@0:
michael@0:
>>> # Dingus
michael@0: >>> my_dingus = dingus.Dingus()
michael@0: >>> method3 = my_dingus.method1.return_value.method2.return_value.method3
michael@0: >>> method3.return_value = 'some value'
michael@0: >>> assertEqual('some value', my_dingus.method1().method2().method3(1, 2))
michael@0: >>> assert method3.calls('()', 1, 2).once()
michael@0: 
michael@0:
michael@0:
>>> # fudge
michael@0: >>> @fudge.test
michael@0: ... def test():
michael@0: ...     my_fake = fudge.Fake()
michael@0: ...     (my_fake
michael@0: ...      .expects('method1')
michael@0: ...      .returns_fake()
michael@0: ...      .expects('method2')
michael@0: ...      .returns_fake()
michael@0: ...      .expects('method3')
michael@0: ...      .with_args(1, 2)
michael@0: ...      .returns('some value'))
michael@0: ...     assertEqual('some value', my_fake.method1().method2().method3(1, 2))
michael@0: ...
michael@0: >>> test()
michael@0: 
michael@0:
michael@0:
michael@0:
michael@0:

Mocking a context manager

michael@0:

Examples for mock, Dingus and fudge only (so far):

michael@0:
>>> # mock
michael@0: >>> my_mock = mock.MagicMock()
michael@0: >>> with my_mock:
michael@0: ...     pass
michael@0: ...
michael@0: >>> my_mock.__enter__.assert_called_with()
michael@0: >>> my_mock.__exit__.assert_called_with(None, None, None)
michael@0: 
michael@0:
michael@0:
>>> # Dingus (nothing special here; all dinguses are "magic mocks")
michael@0: >>> my_dingus = dingus.Dingus()
michael@0: >>> with my_dingus:
michael@0: ...     pass
michael@0: ...
michael@0: >>> assert my_dingus.__enter__.calls()
michael@0: >>> assert my_dingus.__exit__.calls('()', None, None, None)
michael@0: 
michael@0:
michael@0:
>>> # fudge
michael@0: >>> my_fake = fudge.Fake().provides('__enter__').provides('__exit__')
michael@0: >>> with my_fake:
michael@0: ...     pass
michael@0: ...
michael@0: 
michael@0:
michael@0:
michael@0:
michael@0:

Mocking the builtin open used as a context manager

michael@0:

Example for mock only (so far):

michael@0:
>>> # mock
michael@0: >>> my_mock = mock.MagicMock()
michael@0: >>> with mock.patch('__builtin__.open', my_mock):
michael@0: ...     manager = my_mock.return_value.__enter__.return_value
michael@0: ...     manager.read.return_value = 'some data'
michael@0: ...     with open('foo') as h:
michael@0: ...         data = h.read()
michael@0: ...
michael@0: >>> data
michael@0: 'some data'
michael@0: >>> my_mock.assert_called_once_with('foo')
michael@0: 
michael@0:
michael@0:

or:

michael@0:
>>> # mock
michael@0: >>> with mock.patch('__builtin__.open') as my_mock:
michael@0: ...     my_mock.return_value.__enter__ = lambda s: s
michael@0: ...     my_mock.return_value.__exit__ = mock.Mock()
michael@0: ...     my_mock.return_value.read.return_value = 'some data'
michael@0: ...     with open('foo') as h:
michael@0: ...         data = h.read()
michael@0: ...
michael@0: >>> data
michael@0: 'some data'
michael@0: >>> my_mock.assert_called_once_with('foo')
michael@0: 
michael@0:
michael@0:
>>> # Dingus
michael@0: >>> my_dingus = dingus.Dingus()
michael@0: >>> with dingus.patch('__builtin__.open', my_dingus):
michael@0: ...     file_ = open.return_value.__enter__.return_value
michael@0: ...     file_.read.return_value = 'some data'
michael@0: ...     with open('foo') as h:
michael@0: ...         data = f.read()
michael@0: ...
michael@0: >>> data
michael@0: 'some data'
michael@0: >>> assert my_dingus.calls('()', 'foo').once()
michael@0: 
michael@0:
michael@0:
>>> # fudge
michael@0: >>> from contextlib import contextmanager
michael@0: >>> from StringIO import StringIO
michael@0: >>> @contextmanager
michael@0: ... def fake_file(filename):
michael@0: ...     yield StringIO('sekrets')
michael@0: ...
michael@0: >>> with fudge.patch('__builtin__.open') as fake_open:
michael@0: ...     fake_open.is_callable().calls(fake_file)
michael@0: ...     with open('/etc/password') as f:
michael@0: ...         data = f.read()
michael@0: ...
michael@0: fake:__builtin__.open
michael@0: >>> data
michael@0: 'sekrets'
michael@0: 
michael@0:
michael@0:
michael@0:
michael@0: michael@0: michael@0:
michael@0:
michael@0:
michael@0:
michael@0:
michael@0:

Table Of Contents

michael@0: michael@0: michael@0:

Previous topic

michael@0:

Further Examples

michael@0:

Next topic

michael@0:

CHANGELOG

michael@0:

This Page

michael@0: michael@0: michael@0: michael@0:
michael@0:
michael@0:
michael@0:
michael@0: michael@0: michael@0: michael@0: