Я пытаюсь издеваться над цепным вызовом класса Djangos model.Manager()
. А пока я хочу поиздеваться над методом values()
и filter()
.
Чтобы проверить это, я создал небольшой тестовый проект:
- Создайте виртуальную среду
- Беги
pip install django mock mock-django nose django-nose
- Создать проект
django-admin.py startproject mocktest
- Создать приложение
manage.py startapp mockme
- Добавьте
django_nose
иmocktest.mockme
вINSTALLED_APPS
(settings.py) - Добавьте
TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
в settings.py
Чтобы убедиться, что все настроено правильно, я запустил manage.py test
. Запускается один тест, стандартный тест, который Django создает при создании приложения.
Следующее, что я сделал, это создал очень простую модель.
mockme/models.py
from django.db import models
class MyModel(models.Model):
name = models.CharField(max_length=50)
Следующее, что я сделал, это создал простую функцию, использующую MyModel
. Эту функцию я хочу протестировать позже.
mockme/functions.py
from models import MyModel
def chained_query():
return MyModel.objects.values('name').filter(name='Frank')
Здесь ничего особенного не происходит. Функция фильтрует объекты MyModel, чтобы найти все экземпляры, где name='Frank'
. Вызов values() вернет ValuesQuerySet
, который будет содержать только поле имени всех найденных экземпляров MyModel.
mockme/tests.py
import mock
from django.test import TestCase
from mocktest.mockme.models import MyModel
from mocktest.mockme.functions import chained_query
from mock_django.query import QuerySetMock
class SimpleTest(TestCase):
def test_chained_query(self):
# without mocked queryset the result should be 0
result = chained_query()
self.assertEquals(result.count(), 0)
# now try to mock values().filter() and reeturn
# one 'Frank'.
qsm = QuerySetMock(MyModel, MyModel(name='Frank'))
with mock.patch('django.db.models.Manager.filter', qsm):
result = chained_query()
self.assertEquals(result.count(), 1)
Первый assertEquals будет оценен как успешный. Экземпляры не возвращаются, так как диспетчер моделей еще не смоделирован. Когда вызывается второй assertEquals, я ожидаю, что result
будет содержать экземпляр MyModel, который я добавил в качестве возвращаемого значения в QuerySetMock:
qsm = QuerySetMock(MyModel, MyModel(name='Frank'))
Я издевался над методом filter()
, а не над методом values()
, так как обнаружил, что это будет последний оцененный вызов, хотя я не уверен.
Тест завершится ошибкой, потому что вторая переменная результата не будет содержать никаких экземпляров MyModel.
Чтобы убедиться, что метод filter()
действительно издевается, я добавил оператор "debug print":
from django.db import models
print models.Manager.filter
который вернулся:
<SharedMock name='mock.iterator' id='4514208912'>
Что я делаю не так?