【发布时间】:2012-10-04 17:38:48
【问题描述】:
我试图模拟 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 包含我作为返回值添加到 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'>
我做错了什么?
【问题讨论】:
标签: python django django-orm python-mock django-nose