14

Djangosmodel.Manager()クラスの連鎖呼び出しをモックしようとしています。values()今のところ、 andfilter()メソッドをモックしたいと思います。

小さなテスト プロジェクトを作成したことをテストするには、次のようにします。

  1. 仮想環境を作成する
  2. 走るpip install django mock mock-django nose django-nose
  3. プロジェクトを作成するdjango-admin.py startproject mocktest
  4. アプリを作成するmanage.py startapp mockme
  5. django_noseと(settings.py)mocktest.mockmeに追加INSTALLED_APPS
  6. TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'settings.pyに追加

すべてが正しくセットアップされていることを確認するために、実行しましたmanage.py test。1 つのテストが実行されます。これは、アプリを作成するときに 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 インスタンスの 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)

最初の assertEquals は成功と評価されます。モデル Manager はまだモックされていないため、インスタンスは返されません。2 番目の assertEquals が呼び出されるとresult、QuerySetMock への戻り値として追加した MyModel インスタンスが含まれることが期待されます。

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

よくわかりませんが、メソッドが最後に評価された呼び出しになることがわかったのでfilter()、メソッドではなくメソッドをモックしました。values()

2 番目の結果変数には MyModel インスタンスが含まれないため、テストは失敗します。

メソッドが本当にモックされていることを確認するためにfilter()、「debug print」ステートメントを追加しました。

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

返された:

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

私は何を間違っていますか?

4

2 に答える 2

12

これを試して:

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)
于 2014-07-25T16:44:22.167 に答える