2012-10-14 9 views
10

Ich versuche, einen verketteten Anruf auf der Djangos model.Manager() Klasse zu verspotten. Für jetzt möchte ich die Methode values() und filter() verspotten.Django ORM - Mock Werte(). Filter() Kette

Um zu testen, dass ich ein kleines Testprojekt erstellt:

  1. eine virtuelle Umgebung
  2. Run erstellen pip install django mock mock-django nose django-nose
  3. Erstellen Sie ein Projekt django-admin.py startproject mocktest
  4. eine App manage.py startapp mockme
  5. hinzufügen erstellen django_nose und mocktest.mockme zu INSTALLED_APPS (settings.py)
  6. TEST_RUNNER = 'django_nose.NoseTestSuiteRunner' hinzufügen

settings.py ist, dass alles verfiy Setup richtig lief ich manage.py test. Ein Test wird ausgeführt, der Standardtest, den Django erstellt, wenn Sie eine App erstellen.

Als nächstes habe ich ein sehr einfaches Modell erstellt.

mockme/models.py

from django.db import models 

class MyModel(models.Model): 
    name = models.CharField(max_length=50) 

Das nächste, was ich tat, war eine einfache Funktion zu erstellen, die MyModel verwendet. Das ist die Funktion, die ich später testen möchte.

mockme/functions.py

from models import MyModel 

def chained_query(): 
    return MyModel.objects.values('name').filter(name='Frank') 

Nichts Besonderes geschieht hier. Die Funktion filtert die MyModel-Objekte, um alle Instanzen zu finden, in denen name='Frank'. Der Aufruf von values ​​() gibt eine ValuesQuerySet zurück, die nur das Namensfeld aller gefundenen MyModel-Instanzen enthält.

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) 

Die erste assertEquals wird als erfolgreich bewerten. Es werden keine Instanzen zurückgegeben, da der Modellmanager noch nicht verspottet wurde. Wenn die zweite assertEquals I erwarten result genannt MyModel Instanz I enthalten als Rückgabewert auf den QuerySetMock hinzugefügt:

qsm = QuerySetMock(MyModel, MyModel(name='Frank')) 

ich die filter() Methode verspottet und nicht die values() Methode, da fand ich wird es die letzte ausgewertet werden ruf an, obwohl ich mir nicht sicher bin.

Der Test schlägt fehl, weil die zweite Ergebnisvariable keine MyModel-Instanzen enthält.

Um sicher zu sein, dass die filter() Methode wirklich eine "Debug-print" Aussage, die ich verspottet wird hinzugefügt:

from django.db import models 
print models.Manager.filter 

die zurückgegeben:

<SharedMock name='mock.iterator' id='4514208912'> 

Was mache ich falsch?

Antwort

4

Try this:

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

Sollte das nicht sein ' 'Werte')'? – Splatmistro