Django Mock Queries
django-mock-queries is a Python library designed for mocking Django queryset functions in memory during testing. It provides a way to simulate Django's ORM behavior, including method chaining, Q object filtering, aggregates, and CRUD operations, without needing a live database connection. The library is actively maintained, with the current version being 2.3.0, and receives regular updates to support newer Python and Django versions.
Common errors
-
NotSupportedError: Mock database tried to execute SQL for <Model> model.
cause The `monkey_patch_test_db()` function has replaced Django's database connection with a mock, and a test is attempting a real database operation.fixIdentify tests that require a live database. Either configure your test runner to use a real database for those specific tests, or mark those tests to be skipped when `monkey_patch_test_db()` is active. -
AttributeError: 'list' object has no attribute 'filter'
cause A mocked queryset method returned a plain Python list, and a subsequent chained queryset method (like `filter()`, `order_by()`, `exists()`) was called on it. This typically happens when `mock_object.some_method.return_value = [...]` instead of another mock queryset.fixEnsure that any chained mock methods return another `MockSet` instance or a mock object configured to mimic a `QuerySet`'s chainable behavior. For instance, `mock_manager.filter.return_value = MockSet([...])` or if chaining itself is the goal, `mock_queryset.filter.return_value = mock_queryset`. -
ModuleNotFoundError: No module named 'django_mock_queries'
cause The `django-mock-queries` package is not installed in the current Python environment or virtual environment.fixInstall the library using `pip install django-mock-queries`. Ensure your virtual environment is activated if you are using one.
Warnings
- breaking Version 2.2.0 dropped support for Python 2.x. Projects still using Python 2 must remain on `django-mock-queries<2.2.0`.
- gotcha When using `monkey_patch_test_db()` for in-memory tests, any tests that *require* actual database interaction will raise a `NotSupportedError`.
- gotcha Chaining mock queryset methods (e.g., `Manager.filter().order_by().exists()`) requires careful handling of `return_value` to ensure each step returns a mock object that supports subsequent method calls, not a plain list.
- gotcha Complex Q-object filters, custom lookups, or specific field types (like JSONField with list values) may not be fully replicated or might return unexpected results compared to Django's actual ORM.
Install
-
pip install django-mock-queries
Imports
- MockSet
from django_mock_queries.query import MockSet
- MockModel
from django_mock_queries.query import MockModel
- monkey_patch_test_db
from django_mock_queries.mocks import monkey_patch_test_db
Quickstart
from django.db.models import Avg, Q
from django_mock_queries.query import MockSet, MockModel
# Example 1: Basic filtering
qs = MockSet(
MockModel(mock_name='john', email='john@gmail.com'),
MockModel(mock_name='jeff', email='jeff@hotmail.com'),
MockModel(mock_name='bill', email='bill@gmail.com'),
)
results = [x for x in qs.all().filter(email__icontains='gmail.com').select_related('address')]
# print(results) # Expected: [<MockModel: john>, <MockModel: bill>]
# Example 2: Aggregation
qs_agg = MockSet(
MockModel(mock_name='model s', msrp=70000),
MockModel(mock_name='model x', msrp=80000),
MockModel(mock_name='model 3', msrp=35000),
)
agg_result = qs_agg.all().aggregate(Avg('msrp'))
# print(agg_result) # Expected: {'msrp__avg': 61666.666...}
# Example 3: Filtering with Q objects
qs_q = MockSet(
MockModel(mock_name='model x', make='tesla', country='usa'),
MockModel(mock_name='s-class', make='mercedes', country='germany'),
MockModel(mock_name='s90', make='volvo', country='sweden'),
)
q_results = [x for x in qs_q.all().filter(Q(make__iexact='tesla') | Q(country__iexact='germany'))]
# print(q_results) # Expected: [<MockModel: model x>, <MockModel: s-class>]
# Example 4: Creating objects
qs_create = MockSet(cls=MockModel)
new_obj = qs_create.create(mock_name='my_object', foo='1', bar='a')
# print(new_obj) # Expected: <MockModel: my_object>
# print([x for x in qs_create]) # Expected: [<MockModel: my_object>]