我試圖模擬Djangos model.Manager()
類中的鏈接調用。現在我想嘲笑values()
和filter()
方法。Django ORM - 模擬值()。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
包含我添加返回值爲QuerySetMock的爲MyModel實例:
qsm = QuerySetMock(MyModel, MyModel(name='Frank'))
我嘲笑了filter()
方法,而不是values()
方法,因爲我覺得這將是最後評估打電話,雖然我不確定。
測試將失敗,因爲第二個結果變量將不包含任何MyModel實例。
可以肯定的是,filter()
方法真的是嘲笑我加了一個「調試打印」聲明:
from django.db import models
print models.Manager.filter
其返回:
<SharedMock name='mock.iterator' id='4514208912'>
我在做什麼錯?
應該說不是' '值')'? – Splatmistro