2012-10-14 63 views
10

我試圖模擬Djangos model.Manager()類中的鏈接調用。現在我想嘲笑values()filter()方法。Django ORM - 模擬值()。filter()鏈

爲了測試我創建了一個小測試項目:

  1. 創建虛擬環境
  2. 運行pip install django mock mock-django nose django-nose
  3. 創建項目django-admin.py startproject mocktest
  4. 創建應用manage.py startapp mockme
  5. 添加django_nosemocktest.mockmeINSTALLED_APPS(settings.py)
  6. 添加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'> 

我在做什麼錯?

回答

4

試試這個:

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) 
+0

應該說不是' '值')'? – Splatmistro