Jen*_*ens 13 python django django-orm python-mock django-nose
我试图在Djangos model.Manager()类上模拟一个链式调用.现在我想嘲笑values()和filter()方法.
为了测试我创建了一个小测试项目:
pip install django mock mock-django nose django-nosedjango-admin.py startproject mocktestmanage.py startapp mockmedjango_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)
Run Code Online (Sandbox Code Playgroud)
我做的下一件事是创建一个使用的简单函数MyModel.这是我想要稍后测试的功能.
mockme/functions.py
from models import MyModel
def chained_query():
return MyModel.objects.values('name').filter(name='Frank')
Run Code Online (Sandbox Code Playgroud)
这里没有什么特别的事情发生.该函数正在过滤MyModel对象以查找其中的所有实例name='Frank'.对values()的调用将返回一个ValuesQuerySet只包含所有找到的MyModel实例的name字段的内容.
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)
Run Code Online (Sandbox Code Playgroud)
第一个assertEquals将评估成功.由于模型管理器尚未模拟,因此不返回任何实例.当第二个assertEquals被调用时,我希望result包含我作为返回值添加到QuerySetMock的MyModel实例:
qsm = QuerySetMock(MyModel, MyModel(name='Frank'))
Run Code Online (Sandbox Code Playgroud)
我嘲笑了filter()方法,而不是values()方法,因为我发现它将是最后一次评估的电话,但我不确定.
测试将失败,因为第二个结果变量不包含任何MyModel实例.
为了确保该filter()方法真的被模拟,我添加了一个"debug print"语句:
from django.db import models
print models.Manager.filter
Run Code Online (Sandbox Code Playgroud)
返回:
<SharedMock name='mock.iterator' id='4514208912'>
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
小智 8
试试这个:
import mock
from mocktest.mockme.models import MyModel
class SimpleTest(TestCase):
def test_chained_query(self):
my_model_value_mock = mock.patch(MyModel.objects, 'value')
my_model_value_mock.return_value.filter.return_value.count.return_value = 10000
self.assertTrue(my_model_value_mock.return_value.filter.return_value.count.called)
Run Code Online (Sandbox Code Playgroud)
@Gin 的回答让我找到了大部分方法,但就我而言,我正在修补MyModel.objects,而我嘲笑的查询如下所示:
MyModel.objects.filter(arg1=user, arg2=something_else).order_by('-something').first()
所以这对我有用:
@patch('MyModel.objects')
def test_a_function(mock, a_fixture):
mock.filter.return_value.order_by.return_value.first.return_value = a_fixture
result = the_func_im_testing(arg1, arg2)
assert result == 'value'
Run Code Online (Sandbox Code Playgroud)
此外,修补属性的顺序很重要,并且必须与您在测试函数中调用它们的顺序相匹配。
| 归档时间: |
|
| 查看次数: |
5394 次 |
| 最近记录: |