Skip to content

Commit fafe479

Browse files
committed
migrated tests to lookup_ and added data
1 parent 139d0b4 commit fafe479

File tree

4 files changed

+77
-50
lines changed

4 files changed

+77
-50
lines changed

tests/expression_converter_/models.py

Lines changed: 0 additions & 15 deletions
This file was deleted.

tests/expression_converter_/test_filter_conversion.py

Lines changed: 0 additions & 34 deletions
This file was deleted.

tests/lookup_/models.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,10 @@ class Meta:
1717

1818
def __str__(self):
1919
return str(self.num)
20+
21+
22+
class NullableJSONModel(models.Model):
23+
value = models.JSONField(blank=True, null=True)
24+
25+
class Meta:
26+
required_db_features = {"supports_json_field"}

tests/lookup_/tests.py

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
from bson import ObjectId
2+
from django.db import connection
13
from django.test import TestCase
24

35
from django_mongodb_backend.test import MongoTestCaseMixin
46

5-
from .models import Book, Number
7+
from .models import Book, NullableJSONModel, Number
68

79

810
class NumericLookupTests(TestCase):
@@ -66,3 +68,70 @@ def test_eq_and_in(self):
6668
"lookup__book",
6769
[{"$match": {"$and": [{"isbn": {"$in": ("12345", "56789")}}, {"title": "Moby Dick"}]}}],
6870
)
71+
72+
73+
class NullValueLookupTests(MongoTestCaseMixin, TestCase):
74+
_OPERATOR_PREDICATE_MAP = {
75+
"eq": lambda field: {field: None},
76+
"in": lambda field: {field: {"$in": [None]}},
77+
}
78+
79+
@classmethod
80+
def setUpTestData(cls):
81+
cls.book_objs = Book.objects.bulk_create(
82+
Book(title=f"Book {i}", isbn=str(i)) for i in range(5)
83+
)
84+
85+
cls.null_objs = NullableJSONModel.objects.bulk_create(NullableJSONModel() for _ in range(5))
86+
cls.null_objs.append(NullableJSONModel.objects.create(value={"name": None}))
87+
cls.unique_id = ObjectId()
88+
89+
def _test_none_filter_nullable_json(self, op, predicate, field):
90+
with self.assertNumQueries(1) as ctx:
91+
list(NullableJSONModel.objects.filter(**{f"{field}__{op}": None}))
92+
self.assertAggregateQuery(
93+
ctx.captured_queries[0]["sql"],
94+
"lookup__nullablejsonmodel",
95+
[{"$match": {"$and": [{"$exists": False}, predicate(field)]}}],
96+
)
97+
self.assertQuerySetEqual(
98+
NullableJSONModel.objects.filter(**{f"{field}__{op}": None}),
99+
[],
100+
)
101+
102+
def _test_none_filter_binary_operator(self, op, predicate, field):
103+
with self.assertNumQueries(1) as ctx:
104+
list(Book.objects.filter(**{f"{field}__{op}": None}))
105+
self.assertAggregateQuery(
106+
ctx.captured_queries[0]["sql"],
107+
"lookup__book",
108+
[
109+
{
110+
"$match": {
111+
"$or": [
112+
{"$and": [{field: {"$exists": True}}, predicate(field)]},
113+
{"$expr": {"$eq": [{"$type": f"${field}"}, "missing"]}},
114+
]
115+
}
116+
}
117+
],
118+
)
119+
self.assertQuerySetEqual(Book.objects.filter(**{f"{field}__{op}": None}), [])
120+
121+
def _test_with_raw_data(self, model, test_function):
122+
collection = connection.database.get_collection(model._meta.db_table)
123+
try:
124+
collection.insert_one({"_id": self.unique_id})
125+
126+
for op, predicate in self._OPERATOR_PREDICATE_MAP.items():
127+
with self.subTest(op=op):
128+
test_function(op, predicate)
129+
130+
finally:
131+
collection.delete_one({"_id": self.unique_id})
132+
133+
def test_none_filter_nullable_json(self):
134+
self._test_with_raw_data(NullableJSONModel, self._test_none_filter_nullable_json)
135+
136+
def test_none_filter_binary_operator(self):
137+
self._test_with_raw_data(Book, self._test_none_filter_binary_operator)

0 commit comments

Comments
 (0)