From 088d5d32d6e5671d51f113dea3ecc5b6852d7a84 Mon Sep 17 00:00:00 2001 From: Jeremy Boyd Date: Mon, 19 Aug 2013 20:28:01 -0500 Subject: [PATCH 1/3] Fix whitespace stuff that was breaking pep8; not bothering with new line length rec since pep8 isn't updated for this yet --- mock_django/shared.py | 3 +-- tests/mock_django/http/tests.py | 2 +- tests/mock_django/query/tests.py | 3 +++ tests/mock_django/signals/tests.py | 1 + 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/mock_django/shared.py b/mock_django/shared.py index d7ed9be..3e673f5 100644 --- a/mock_django/shared.py +++ b/mock_django/shared.py @@ -70,8 +70,7 @@ def assert_chain_calls(self, *calls): not_found.append(kall) if not_found: if self.__parent.mock_calls: - message = '%r not all found in call list, %d other(s) were:\n%r' % (not_found, len(self.__parent.mock_calls), - self.__parent.mock_calls) + message = '%r not all found in call list, %d other(s) were:\n%r' % (not_found, len(self.__parent.mock_calls), self.__parent.mock_calls) else: message = 'no calls were found' diff --git a/tests/mock_django/http/tests.py b/tests/mock_django/http/tests.py index b43a57a..778b178 100644 --- a/tests/mock_django/http/tests.py +++ b/tests/mock_django/http/tests.py @@ -19,7 +19,7 @@ def test_instance(self): self.assertEqual({}, wsgi_r.META) self.assertEqual({}, wsgi_r.GET) self.assertEqual({}, wsgi_r.POST) - + def test__get_request(self): wsgi_r = WsgiHttpRequest() expected_items = MergeDict({}, {}).items() diff --git a/tests/mock_django/query/tests.py b/tests/mock_django/query/tests.py index 1fc5f32..f9fc343 100644 --- a/tests/mock_django/query/tests.py +++ b/tests/mock_django/query/tests.py @@ -1,9 +1,11 @@ from mock_django.query import QuerySetMock from unittest2 import TestCase + class TestException(Exception): pass + class TestModel(object): def foo(self): pass @@ -11,6 +13,7 @@ def foo(self): def bar(self): return 'bar' + class QuerySetTestCase(TestCase): def test_vals_returned(self): qs = QuerySetMock(None, 1, 2, 3) diff --git a/tests/mock_django/signals/tests.py b/tests/mock_django/signals/tests.py index 7f7e1de..6b1d175 100644 --- a/tests/mock_django/signals/tests.py +++ b/tests/mock_django/signals/tests.py @@ -11,6 +11,7 @@ def test_mock_receiver(self): self.assertEqual(receiver.call_count, 1) sentinel = {} + def side_effect(*args, **kwargs): return sentinel From 67e598f758e67c6a7568f0fc8d16855bf8952e3e Mon Sep 17 00:00:00 2001 From: Jeremy Boyd Date: Mon, 19 Aug 2013 20:51:19 -0500 Subject: [PATCH 2/3] Run Travis against most recent versions of Django --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4a7aaf3..6e20af5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,8 +6,8 @@ python: env: - DJANGO=1.2.7 - DJANGO=1.3.1 - - DJANGO=1.4.5 - - DJANGO=1.5.1 + - DJANGO=1.4.6 + - DJANGO=1.5.2 install: - sudo apt-get install libevent-dev - sudo pip install Django==$DJANGO --use-mirrors From 37cf01a0c28f2b78cf30103b5714c29e50b6c6ed Mon Sep 17 00:00:00 2001 From: Jeremy Boyd Date: Thu, 22 Aug 2013 22:51:29 -0500 Subject: [PATCH 3/3] Allow chaining of QuerySet-returning methods --- README.rst | 3 ++- mock_django/query.py | 28 +++++++++++++++++++++++++--- tests/mock_django/query/tests.py | 17 +++++++++++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index 41ec1dc..87051e0 100644 --- a/README.rst +++ b/README.rst @@ -11,12 +11,13 @@ Inside your virtualenv:: >>> settings.configure() # required to convince Django it's properly configured >>> from mock_django.query import QuerySetMock >>> class Post(object): pass + ... >>> qs = QuerySetMock(Post, 1, 2, 3) >>> list(qs.all()) [1, 2, 3] >>> qs.count() 3 - >>> qs.all().filter() + >>> list(qs.all().filter()) [1, 2, 3] See tests for more examples. diff --git a/mock_django/query.py b/mock_django/query.py index 75c5a3d..363179a 100644 --- a/mock_django/query.py +++ b/mock_django/query.py @@ -5,23 +5,36 @@ :copyright: (c) 2012 DISQUS. :license: Apache License 2.0, see LICENSE for more details. """ +import copy import mock from .shared import SharedMock __all__ = ('QuerySetMock',) +QUERYSET_RETURNING_METHODS = ['filter', 'exclude', 'order_by', 'reverse', + 'distinct', 'none', 'all', 'select_related', + 'prefetch_related', 'defer', 'only', 'using', + 'select_for_update'] + def QuerySetMock(model, *return_value): """ + Get a SharedMock that returns self for most attributes and a new copy of + itself for any method that ordinarily generates QuerySets. + Set the results to two items: + >>> class Post(object): pass >>> objects = QuerySetMock(Post, 'return', 'values') >>> assert list(objects.filter()) == list(objects.all()) Force an exception: >>> objects = QuerySetMock(Post, Exception()) + + Chain calls: + >>> objects.all().filter(filter_arg='dummy') """ def make_get(self, model): @@ -35,6 +48,11 @@ def _get(*a, **k): raise model.DoesNotExist return _get + def make_qs_returning_method(self): + def _qs_returning_method(*a, **k): + return copy.deepcopy(self) + return _qs_returning_method + def make_getitem(self): def _getitem(k): if isinstance(k, slice): @@ -62,18 +80,22 @@ def _iterator(*a, **k): else: model = mock.MagicMock() - m = SharedMock(reserved=['count', 'exists']) + m = SharedMock(reserved=['count', 'exists'] + QUERYSET_RETURNING_METHODS) m.__start = None m.__stop = None m.__iter__.side_effect = lambda: iter(m.iterator()) m.__getitem__.side_effect = make_getitem(m) - m.model = model - m.get = make_get(m, actual_model) m.__nonzero__.side_effect = lambda: bool(return_value) m.__len__.side_effect = lambda: len(return_value) m.exists.side_effect = m.__nonzero__ m.count.side_effect = m.__len__ + m.model = model + m.get = make_get(m, actual_model) + + for method_name in QUERYSET_RETURNING_METHODS: + setattr(m, method_name, make_qs_returning_method(m)) + # Note since this is a SharedMock, *all* auto-generated child # attributes will have the same side_effect ... might not make # sense for some like count(). diff --git a/tests/mock_django/query/tests.py b/tests/mock_django/query/tests.py index f9fc343..c43ec71 100644 --- a/tests/mock_django/query/tests.py +++ b/tests/mock_django/query/tests.py @@ -55,6 +55,23 @@ def test_raises_exception_when_accessed(self): qs = QuerySetMock(None, TestException()) self.assertRaises(TestException, lambda x: x[0], qs) + def test_chaining_calls_works(self): + """ + Chained calls to QS-returning methods should return new QuerySetMocks. + """ + qs = QuerySetMock(None, 1, 2, 3) + qs.all().filter(filter_arg='dummy') + qs.filter(filter_arg='dummy').order_by('-date') + + def test_chained_calls_return_new_querysetmocks(self): + qs = QuerySetMock(None, 1, 2, 3) + qs_all = qs.all() + qs_filter = qs.filter() + qs_all_filter = qs.filter().all() + + self.assertIsNot(qs_all, qs_filter) + self.assertIsNot(qs_filter, qs_all_filter) + # Test reserved methods def test_count_is_scalar(self): qs = QuerySetMock(None, 1, 2, 3)