Created for the Django Toronto meetup, a quick tour through the Python mock package.
mock==0.8.0
View Slide
Who am I?Dan Langer@dlanger[email protected]daniel.langer.me
>> import mock>> dir(mock)['Mock', 'patch', ...]
>> from mock import Mock
Mocks all the way down>> k = Mock()>> k.foo.bar>> k.foo.bar
Configure your mocks>> from django.contrib.auth.modelsimport User>> user1_mock = Mock()>> user1_mock.foo>> user2_mock = Mock(spec=User)>> user2_mock.fooAttributeError: ...
Configure your mocks>> rmock = Mock(return_value=5)>> rmock(), rmock(4), rmock("W")(5, 5, 5)>> smock = Mock(side_effect=[1,2])>> smock(), smock()(1, 2)>> emock = Mock(side_effect=Exception)>> emock()Exception: ...
Inspect your mocks>> imock = Mock(return_value=None)>> imock()>> imock.call_count1>> imock(1, 2, 3, demo="ok")>> imock.call_args_list[call(1), call(1,2,3,demo='ok')]
>> from mock import patch
Daniel Coomber
Patch all the things# utils.pydef load_token(user)r = StrictRedis(host=...)[...]raw_token = r.rpop(token_id)return '--'.join([raw_token, ...])# tests.pydef test_load_token(self):redis_mock = Mock()redis_mock.return_value.rpop \.return_value = 'TEST_TOKEN'with patch('utils.StrictRedis', redis_mock):load_token(self.test_user)self.assertEqual(...)
Patch celery# tasks.py@taskdef process_chunk(chunk):pass@taskdef process_file(file):tasks = []for ...st = process_chunk.subtask(chunk)tasks.append(st)process = TaskSet(tasks=tasks)process.apply_async()
Patch celery# tests.pydef test_process_file__two_subtasks(self):pc_mock = Mock()with patch('tasks.process_chunk',pc_mock):process_file.delay(...)self.assertEqual(pc_mock.call_count, 2)#Fails
Patch celery# tests.pydef test_process_file__two_subtasks(self):pc_mock = Mock()with patch('tasks.process_chunk.subtask',pc_mock):process_file.delay(...)self.assertEqual(pc_mock.call_count, 2)
Patch built-ins# utils.pyimport message_defsdef load_defaults(id)if getattr(message_defs, id, None):[...]# tests.pydef test_load_defaults(self):with patch('__builtins__.getattr',return_value='Hi'):load_defaults('welcome')self.assertEqual(...)
Patch built-ins# utils.pyimport message_defsdef load_defaults(id)if getattr(message_defs, id, None):[...]# tests.pydef test_load_defaults(self):with patch('utils.getattr',create=True,return_value='Hi'):load_defaults('welcome')self.assertEqual(...)
Patch Djangodef test_template:mock_get_template = Mock(return_value=Template("Hi {{ username }}"))with patch('package.module.get_template',mock_get_template):[...]def test_verify_user(self):mock_get = Mock()mock_get.return_value = Mock(spec=User)with patch('utils.User.objects.get',mock_get):[...]
Patch the ORM...sparingly# User.objects.filter(...).exclude(...) \# .order_by(...)def test_user_filter(self):mock_filter = Mock()mock_filter.return_value.exclude \.return_value.order_by.return_value = [...]with patch('utils.User.objects.filter',mock_filter):[...]
Keep Reading@decorator syntaxcreate_autospecMagicMock [...]http://www.voidspace.org.uk/python/mock/