Django ORM – valores simulados (). Cadena de filtro ()

Estoy intentando burlarme de una llamada encadenada en el modelo model.Manager() class. Por ahora quiero burlarme de los values() y del método filter() .

Para probar que he creado un pequeño proyecto de prueba:

  1. Crear un entorno virtual.
  2. Ejecutar pip install django mock mock-django nose django-nose
  3. Crear un proyecto django-admin.py startproject mocktest
  4. Crear una aplicación manage.py startapp mockme
  5. Agregue django_nose y mocktest.mockme a INSTALLED_APPS (settings.py)
  6. Agregue TEST_RUNNER = 'django_nose.NoseTestSuiteRunner' a settings.py

Para verificar que todo está configurado correctamente, manage.py test . Se ejecuta una prueba, la prueba estándar que crea Django cuando crea una aplicación.

Lo siguiente que hice fue crear un modelo muy simple.

mockme / modelos.py

     from django.db import models class MyModel(models.Model): name = models.CharField(max_length=50) 

    Lo siguiente que hice fue crear una función simple que usa MyModel . Esa es la función que quiero probar más tarde.

    mockme / functions.py

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

    Nada especial está sucediendo aquí. La función está filtrando los objetos MyModel para encontrar todas las instancias donde name='Frank' . La llamada a los valores () devolverá un ValuesQuerySet que solo contendrá el campo de nombre de todas las instancias de MyModel encontradas.

    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) 

    El primer assertEquals evaluará como exitoso. No se devuelven instancias ya que el modelo Manager aún no se ha burlado. Cuando se llama al segundo assertEquals, espero que el result contenga la instancia de MyModel que agregué como valor de retorno al QuerySetMock:

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

    Me burlé del método del filter() y no del método de los values() porque descubrí que será la última llamada evaluada, aunque no estoy seguro.

    La prueba fallará porque la segunda variable de resultado no contendrá ninguna instancia de MyModel.

    Para estar seguro de que el método filter() está realmente burlado, agregué una statement de “impresión de depuración”:

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

    el cual regresó:

      

    ¿Qué estoy haciendo mal?

    Prueba esto:

     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)