michael@0: michael@0: michael@0: michael@0: michael@0: michael@0:
michael@0: michael@0: michael@0:Author: | Michael Foord | michael@0:
---|---|
Version: | 1.0.0 | michael@0:
Date: | 2012/10/07 | michael@0:
Homepage: | Mock Homepage | michael@0:
Download: | Mock on PyPI | michael@0:
Documentation: | PDF Documentation | michael@0:
License: | BSD License | michael@0:
Support: | Mailing list (testing-in-python@lists.idyll.org) | michael@0:
Issue tracker: | Google code project | michael@0:
mock is a library for testing in Python. It allows you to replace parts of michael@0: your system under test with mock objects and make assertions about how they michael@0: have been used.
michael@0:mock is now part of the Python standard library, available as unittest.mock michael@0: in Python 3.3 onwards.
michael@0:mock provides a core Mock class removing the need to create a host michael@0: of stubs throughout your test suite. After performing an action, you can make michael@0: assertions about which methods / attributes were used and arguments they were michael@0: called with. You can also specify return values and set needed attributes in michael@0: the normal way.
michael@0:Additionally, mock provides a patch() decorator that handles patching michael@0: module and class level attributes within the scope of a test, along with michael@0: sentinel for creating unique objects. See the quick guide for michael@0: some examples of how to use Mock, MagicMock and michael@0: patch().
michael@0:Mock is very easy to use and is designed for use with michael@0: unittest. Mock is based on michael@0: the ‘action -> assertion’ pattern instead of ‘record -> replay’ used by many michael@0: mocking frameworks.
michael@0:mock is tested on Python versions 2.4-2.7, Python 3 plus the latest versions of michael@0: Jython and PyPy.
michael@0:The current version is 1.0.0. Mock is stable and widely used. If you do michael@0: find any bugs, or have suggestions for improvements / extensions michael@0: then please contact us.
michael@0:You can checkout the latest development version from the Google Code Mercurial michael@0: repository with the following command:
michael@0:michael@0:michael@0:hg clone https://mock.googlecode.com/hg/ mock
If you have pip, setuptools or distribute you can install mock with:
michael@0:michael@0:michael@0:michael@0:michael@0:easy_install -U mockmichael@0:pip install -U mockmichael@0:
Alternatively you can download the mock distribution from PyPI and after michael@0: unpacking run:
michael@0:michael@0:michael@0:python setup.py install
Mock and MagicMock objects create all attributes and michael@0: methods as you access them and store details of how they have been used. You michael@0: can configure them, to specify return values or limit what attributes are michael@0: available, and then make assertions about how they have been used:
michael@0:>>> from mock import MagicMock
michael@0: >>> thing = ProductionClass()
michael@0: >>> thing.method = MagicMock(return_value=3)
michael@0: >>> thing.method(3, 4, 5, key='value')
michael@0: 3
michael@0: >>> thing.method.assert_called_with(3, 4, 5, key='value')
michael@0:
side_effect allows you to perform side effects, including raising an michael@0: exception when a mock is called:
michael@0:>>> mock = Mock(side_effect=KeyError('foo'))
michael@0: >>> mock()
michael@0: Traceback (most recent call last):
michael@0: ...
michael@0: KeyError: 'foo'
michael@0:
michael@0: >>> values = {'a': 1, 'b': 2, 'c': 3}
michael@0: >>> def side_effect(arg):
michael@0: ... return values[arg]
michael@0: ...
michael@0: >>> mock.side_effect = side_effect
michael@0: >>> mock('a'), mock('b'), mock('c')
michael@0: (1, 2, 3)
michael@0: >>> mock.side_effect = [5, 4, 3, 2, 1]
michael@0: >>> mock(), mock(), mock()
michael@0: (5, 4, 3)
michael@0:
Mock has many other ways you can configure it and control its behaviour. For michael@0: example the spec argument configures the mock to take its specification michael@0: from another object. Attempting to access attributes or methods on the mock michael@0: that don’t exist on the spec will fail with an AttributeError.
michael@0:The patch() decorator / context manager makes it easy to mock classes or michael@0: objects in a module under test. The object you specify will be replaced with a michael@0: mock (or other object) during the test and restored when the test ends:
michael@0:>>> from mock import patch
michael@0: >>> @patch('module.ClassName2')
michael@0: ... @patch('module.ClassName1')
michael@0: ... def test(MockClass1, MockClass2):
michael@0: ... module.ClassName1()
michael@0: ... module.ClassName2()
michael@0:
michael@0: ... assert MockClass1 is module.ClassName1
michael@0: ... assert MockClass2 is module.ClassName2
michael@0: ... assert MockClass1.called
michael@0: ... assert MockClass2.called
michael@0: ...
michael@0: >>> test()
michael@0:
Note
michael@0:When you nest patch decorators the mocks are passed in to the decorated michael@0: function in the same order they applied (the normal python order that michael@0: decorators are applied). This means from the bottom up, so in the example michael@0: above the mock for module.ClassName1 is passed in first.
michael@0:With patch it matters that you patch objects in the namespace where they michael@0: are looked up. This is normally straightforward, but for a quick guide michael@0: read where to patch.
michael@0:As well as a decorator patch can be used as a context manager in a with michael@0: statement:
michael@0:>>> with patch.object(ProductionClass, 'method', return_value=None) as mock_method:
michael@0: ... thing = ProductionClass()
michael@0: ... thing.method(1, 2, 3)
michael@0: ...
michael@0: >>> mock_method.assert_called_once_with(1, 2, 3)
michael@0:
There is also patch.dict() for setting values in a dictionary just michael@0: during a scope and restoring the dictionary to its original state when the test michael@0: ends:
michael@0:>>> foo = {'key': 'value'}
michael@0: >>> original = foo.copy()
michael@0: >>> with patch.dict(foo, {'newkey': 'newvalue'}, clear=True):
michael@0: ... assert foo == {'newkey': 'newvalue'}
michael@0: ...
michael@0: >>> assert foo == original
michael@0:
Mock supports the mocking of Python magic methods. The michael@0: easiest way of using magic methods is with the MagicMock class. It michael@0: allows you to do things like:
michael@0:>>> mock = MagicMock()
michael@0: >>> mock.__str__.return_value = 'foobarbaz'
michael@0: >>> str(mock)
michael@0: 'foobarbaz'
michael@0: >>> mock.__str__.assert_called_with()
michael@0:
Mock allows you to assign functions (or other Mock instances) to magic methods michael@0: and they will be called appropriately. The MagicMock class is just a Mock michael@0: variant that has all of the magic methods pre-created for you (well, all the michael@0: useful ones anyway).
michael@0:The following is an example of using magic methods with the ordinary Mock michael@0: class:
michael@0:>>> mock = Mock()
michael@0: >>> mock.__str__ = Mock(return_value='wheeeeee')
michael@0: >>> str(mock)
michael@0: 'wheeeeee'
michael@0:
For ensuring that the mock objects in your tests have the same api as the michael@0: objects they are replacing, you can use auto-speccing. michael@0: Auto-speccing can be done through the autospec argument to patch, or the michael@0: create_autospec() function. Auto-speccing creates mock objects that michael@0: have the same attributes and methods as the objects they are replacing, and michael@0: any functions and methods (including constructors) have the same call michael@0: signature as the real object.
michael@0:This ensures that your mocks will fail in the same way as your production michael@0: code if they are used incorrectly:
michael@0:>>> from mock import create_autospec
michael@0: >>> def function(a, b, c):
michael@0: ... pass
michael@0: ...
michael@0: >>> mock_function = create_autospec(function, return_value='fishy')
michael@0: >>> mock_function(1, 2, 3)
michael@0: 'fishy'
michael@0: >>> mock_function.assert_called_once_with(1, 2, 3)
michael@0: >>> mock_function('wrong arguments')
michael@0: Traceback (most recent call last):
michael@0: ...
michael@0: TypeError: <lambda>() takes exactly 3 arguments (1 given)
michael@0:
create_autospec can also be used on classes, where it copies the signature of michael@0: the __init__ method, and on callable objects where it copies the signature of michael@0: the __call__ method.
michael@0:Articles, blog entries and other stuff related to testing with Mock:
michael@0:Mock uses unittest2 for its own michael@0: test suite. In order to run it, use the unit2 script that comes with michael@0: unittest2 module on a checkout of the source repository:
michael@0:michael@0:michael@0:unit2 discover
If you have setuptools as well as michael@0: unittest2 you can run:
michael@0:michael@0:michael@0:python setup.py test
On Python 3.2 you can use unittest module from the standard library.
michael@0:michael@0:michael@0:python3.2 -m unittest discover
On Python 3 the tests for unicode are skipped as they are not relevant. On michael@0: Python 2.4 tests that use the with statements are skipped as the with statement michael@0: is invalid syntax on Python 2.4.
michael@0:Documentation for older versions of mock:
michael@0: michael@0:Docs from the in-development version of mock can be found at michael@0: mock.readthedocs.org.
michael@0:Terminology for objects used to replace other ones can be confusing. Terms michael@0: like double, fake, mock, stub, and spy are all used with varying meanings.
michael@0:In classic mock terminology michael@0: mock.Mock is a spy that michael@0: allows for post-mortem examination. This is what I call the “action -> michael@0: assertion” [1] pattern of testing.
michael@0:I’m not however a fan of this “statically typed mocking terminology” michael@0: promulgated by Martin Fowler. It confuses usage michael@0: patterns with implementation and prevents you from using natural terminology michael@0: when discussing mocking.
michael@0:I much prefer duck typing, if an object used in your test suite looks like a michael@0: mock object and quacks like a mock object then it’s fine to call it a mock, no michael@0: matter what the implementation looks like.
michael@0:This terminology is perhaps more useful in less capable languages where michael@0: different usage patterns will require different implementations. michael@0: mock.Mock() is capable of being used in most of the different roles michael@0: described by Fowler, except (annoyingly / frustratingly / ironically) a Mock michael@0: itself!
michael@0:How about a simpler definition: a “mock object” is an object used to replace a michael@0: real one in a system under test.
michael@0:[1] | This pattern is called “AAA” by some members of the testing community; michael@0: “Arrange - Act - Assert”. |